@immich/sql-tools 0.1.1 → 0.2.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/dist/index.d.ts +55 -5
- package/dist/index.js +3015 -32
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,3014 @@
|
|
|
1
|
+
import require$$0 from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import net from 'net';
|
|
4
|
+
import tls from 'tls';
|
|
5
|
+
import crypto from 'crypto';
|
|
6
|
+
import Stream from 'stream';
|
|
7
|
+
import { performance as performance$1 } from 'perf_hooks';
|
|
1
8
|
import { createHash } from 'node:crypto';
|
|
2
9
|
|
|
10
|
+
function getDefaultExportFromCjs (x) {
|
|
11
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var pgConnectionString;
|
|
15
|
+
var hasRequiredPgConnectionString;
|
|
16
|
+
|
|
17
|
+
function requirePgConnectionString () {
|
|
18
|
+
if (hasRequiredPgConnectionString) return pgConnectionString;
|
|
19
|
+
hasRequiredPgConnectionString = 1;
|
|
20
|
+
|
|
21
|
+
//Parse method copied from https://github.com/brianc/node-postgres
|
|
22
|
+
//Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com)
|
|
23
|
+
//MIT License
|
|
24
|
+
|
|
25
|
+
//parses a connection string
|
|
26
|
+
function parse(str, options = {}) {
|
|
27
|
+
//unix socket
|
|
28
|
+
if (str.charAt(0) === '/') {
|
|
29
|
+
const config = str.split(' ');
|
|
30
|
+
return { host: config[0], database: config[1] }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check for empty host in URL
|
|
34
|
+
|
|
35
|
+
const config = {};
|
|
36
|
+
let result;
|
|
37
|
+
let dummyHost = false;
|
|
38
|
+
if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) {
|
|
39
|
+
// Ensure spaces are encoded as %20
|
|
40
|
+
str = encodeURI(str).replace(/%25(\d\d)/g, '%$1');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
try {
|
|
45
|
+
result = new URL(str, 'postgres://base');
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// The URL is invalid so try again with a dummy host
|
|
48
|
+
result = new URL(str.replace('@/', '@___DUMMY___/'), 'postgres://base');
|
|
49
|
+
dummyHost = true;
|
|
50
|
+
}
|
|
51
|
+
} catch (err) {
|
|
52
|
+
// Remove the input from the error message to avoid leaking sensitive information
|
|
53
|
+
err.input && (err.input = '*****REDACTED*****');
|
|
54
|
+
throw err
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// We'd like to use Object.fromEntries() here but Node.js 10 does not support it
|
|
58
|
+
for (const entry of result.searchParams.entries()) {
|
|
59
|
+
config[entry[0]] = entry[1];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
config.user = config.user || decodeURIComponent(result.username);
|
|
63
|
+
config.password = config.password || decodeURIComponent(result.password);
|
|
64
|
+
|
|
65
|
+
if (result.protocol == 'socket:') {
|
|
66
|
+
config.host = decodeURI(result.pathname);
|
|
67
|
+
config.database = result.searchParams.get('db');
|
|
68
|
+
config.client_encoding = result.searchParams.get('encoding');
|
|
69
|
+
return config
|
|
70
|
+
}
|
|
71
|
+
const hostname = dummyHost ? '' : result.hostname;
|
|
72
|
+
if (!config.host) {
|
|
73
|
+
// Only set the host if there is no equivalent query param.
|
|
74
|
+
config.host = decodeURIComponent(hostname);
|
|
75
|
+
} else if (hostname && /^%2f/i.test(hostname)) {
|
|
76
|
+
// Only prepend the hostname to the pathname if it is not a URL encoded Unix socket host.
|
|
77
|
+
result.pathname = hostname + result.pathname;
|
|
78
|
+
}
|
|
79
|
+
if (!config.port) {
|
|
80
|
+
// Only set the port if there is no equivalent query param.
|
|
81
|
+
config.port = result.port;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const pathname = result.pathname.slice(1) || null;
|
|
85
|
+
config.database = pathname ? decodeURI(pathname) : null;
|
|
86
|
+
|
|
87
|
+
if (config.ssl === 'true' || config.ssl === '1') {
|
|
88
|
+
config.ssl = true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (config.ssl === '0') {
|
|
92
|
+
config.ssl = false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) {
|
|
96
|
+
config.ssl = {};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Only try to load fs if we expect to read from the disk
|
|
100
|
+
const fs = config.sslcert || config.sslkey || config.sslrootcert ? require$$0 : null;
|
|
101
|
+
|
|
102
|
+
if (config.sslcert) {
|
|
103
|
+
config.ssl.cert = fs.readFileSync(config.sslcert).toString();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (config.sslkey) {
|
|
107
|
+
config.ssl.key = fs.readFileSync(config.sslkey).toString();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (config.sslrootcert) {
|
|
111
|
+
config.ssl.ca = fs.readFileSync(config.sslrootcert).toString();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (options.useLibpqCompat && config.uselibpqcompat) {
|
|
115
|
+
throw new Error('Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (config.uselibpqcompat === 'true' || options.useLibpqCompat) {
|
|
119
|
+
switch (config.sslmode) {
|
|
120
|
+
case 'disable': {
|
|
121
|
+
config.ssl = false;
|
|
122
|
+
break
|
|
123
|
+
}
|
|
124
|
+
case 'prefer': {
|
|
125
|
+
config.ssl.rejectUnauthorized = false;
|
|
126
|
+
break
|
|
127
|
+
}
|
|
128
|
+
case 'require': {
|
|
129
|
+
if (config.sslrootcert) {
|
|
130
|
+
// If a root CA is specified, behavior of `sslmode=require` will be the same as that of `verify-ca`
|
|
131
|
+
config.ssl.checkServerIdentity = function () {};
|
|
132
|
+
} else {
|
|
133
|
+
config.ssl.rejectUnauthorized = false;
|
|
134
|
+
}
|
|
135
|
+
break
|
|
136
|
+
}
|
|
137
|
+
case 'verify-ca': {
|
|
138
|
+
if (!config.ssl.ca) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
'SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.'
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
config.ssl.checkServerIdentity = function () {};
|
|
144
|
+
break
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
switch (config.sslmode) {
|
|
149
|
+
case 'disable': {
|
|
150
|
+
config.ssl = false;
|
|
151
|
+
break
|
|
152
|
+
}
|
|
153
|
+
case 'prefer':
|
|
154
|
+
case 'require':
|
|
155
|
+
case 'verify-ca':
|
|
156
|
+
case 'verify-full': {
|
|
157
|
+
if (config.sslmode !== 'verify-full') {
|
|
158
|
+
deprecatedSslModeWarning(config.sslmode);
|
|
159
|
+
}
|
|
160
|
+
break
|
|
161
|
+
}
|
|
162
|
+
case 'no-verify': {
|
|
163
|
+
config.ssl.rejectUnauthorized = false;
|
|
164
|
+
break
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return config
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// convert pg-connection-string ssl config to a ClientConfig.ConnectionOptions
|
|
173
|
+
function toConnectionOptions(sslConfig) {
|
|
174
|
+
const connectionOptions = Object.entries(sslConfig).reduce((c, [key, value]) => {
|
|
175
|
+
// we explicitly check for undefined and null instead of `if (value)` because some
|
|
176
|
+
// options accept falsy values. Example: `ssl.rejectUnauthorized = false`
|
|
177
|
+
if (value !== undefined && value !== null) {
|
|
178
|
+
c[key] = value;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return c
|
|
182
|
+
}, {});
|
|
183
|
+
|
|
184
|
+
return connectionOptions
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// convert pg-connection-string config to a ClientConfig
|
|
188
|
+
function toClientConfig(config) {
|
|
189
|
+
const poolConfig = Object.entries(config).reduce((c, [key, value]) => {
|
|
190
|
+
if (key === 'ssl') {
|
|
191
|
+
const sslConfig = value;
|
|
192
|
+
|
|
193
|
+
if (typeof sslConfig === 'boolean') {
|
|
194
|
+
c[key] = sslConfig;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (typeof sslConfig === 'object') {
|
|
198
|
+
c[key] = toConnectionOptions(sslConfig);
|
|
199
|
+
}
|
|
200
|
+
} else if (value !== undefined && value !== null) {
|
|
201
|
+
if (key === 'port') {
|
|
202
|
+
// when port is not specified, it is converted into an empty string
|
|
203
|
+
// we want to avoid NaN or empty string as a values in ClientConfig
|
|
204
|
+
if (value !== '') {
|
|
205
|
+
const v = parseInt(value, 10);
|
|
206
|
+
if (isNaN(v)) {
|
|
207
|
+
throw new Error(`Invalid ${key}: ${value}`)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
c[key] = v;
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
c[key] = value;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return c
|
|
218
|
+
}, {});
|
|
219
|
+
|
|
220
|
+
return poolConfig
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// parses a connection string into ClientConfig
|
|
224
|
+
function parseIntoClientConfig(str) {
|
|
225
|
+
return toClientConfig(parse(str))
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function deprecatedSslModeWarning(sslmode) {
|
|
229
|
+
if (!deprecatedSslModeWarning.warned && typeof process !== 'undefined' && process.emitWarning) {
|
|
230
|
+
deprecatedSslModeWarning.warned = true;
|
|
231
|
+
process.emitWarning(`SECURITY WARNING: The SSL modes 'prefer', 'require', and 'verify-ca' are treated as aliases for 'verify-full'.
|
|
232
|
+
In the next major version (pg-connection-string v3.0.0 and pg v9.0.0), these modes will adopt standard libpq semantics, which have weaker security guarantees.
|
|
233
|
+
|
|
234
|
+
To prepare for this change:
|
|
235
|
+
- If you want the current behavior, explicitly use 'sslmode=verify-full'
|
|
236
|
+
- If you want libpq compatibility now, use 'uselibpqcompat=true&sslmode=${sslmode}'
|
|
237
|
+
|
|
238
|
+
See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode definitions.`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
pgConnectionString = parse;
|
|
243
|
+
|
|
244
|
+
parse.parse = parse;
|
|
245
|
+
parse.toClientConfig = toClientConfig;
|
|
246
|
+
parse.parseIntoClientConfig = parseIntoClientConfig;
|
|
247
|
+
return pgConnectionString;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
var pgConnectionStringExports = requirePgConnectionString();
|
|
251
|
+
const connectionString = /*@__PURE__*/getDefaultExportFromCjs(pgConnectionStringExports);
|
|
252
|
+
|
|
253
|
+
// ESM wrapper for pg-connection-string
|
|
254
|
+
|
|
255
|
+
// Re-export the parse function
|
|
256
|
+
connectionString.parse;
|
|
257
|
+
const parse$1 = connectionString.parse;
|
|
258
|
+
connectionString.toClientConfig;
|
|
259
|
+
connectionString.parseIntoClientConfig;
|
|
260
|
+
|
|
261
|
+
const originCache = new Map()
|
|
262
|
+
, originStackCache = new Map()
|
|
263
|
+
, originError = Symbol('OriginError');
|
|
264
|
+
|
|
265
|
+
const CLOSE = {};
|
|
266
|
+
class Query extends Promise {
|
|
267
|
+
constructor(strings, args, handler, canceller, options = {}) {
|
|
268
|
+
let resolve
|
|
269
|
+
, reject;
|
|
270
|
+
|
|
271
|
+
super((a, b) => {
|
|
272
|
+
resolve = a;
|
|
273
|
+
reject = b;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
this.tagged = Array.isArray(strings.raw);
|
|
277
|
+
this.strings = strings;
|
|
278
|
+
this.args = args;
|
|
279
|
+
this.handler = handler;
|
|
280
|
+
this.canceller = canceller;
|
|
281
|
+
this.options = options;
|
|
282
|
+
|
|
283
|
+
this.state = null;
|
|
284
|
+
this.statement = null;
|
|
285
|
+
|
|
286
|
+
this.resolve = x => (this.active = false, resolve(x));
|
|
287
|
+
this.reject = x => (this.active = false, reject(x));
|
|
288
|
+
|
|
289
|
+
this.active = false;
|
|
290
|
+
this.cancelled = null;
|
|
291
|
+
this.executed = false;
|
|
292
|
+
this.signature = '';
|
|
293
|
+
|
|
294
|
+
this[originError] = this.handler.debug
|
|
295
|
+
? new Error()
|
|
296
|
+
: this.tagged && cachedError(this.strings);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
get origin() {
|
|
300
|
+
return (this.handler.debug
|
|
301
|
+
? this[originError].stack
|
|
302
|
+
: this.tagged && originStackCache.has(this.strings)
|
|
303
|
+
? originStackCache.get(this.strings)
|
|
304
|
+
: originStackCache.set(this.strings, this[originError].stack).get(this.strings)
|
|
305
|
+
) || ''
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
static get [Symbol.species]() {
|
|
309
|
+
return Promise
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
cancel() {
|
|
313
|
+
return this.canceller && (this.canceller(this), this.canceller = null)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
simple() {
|
|
317
|
+
this.options.simple = true;
|
|
318
|
+
this.options.prepare = false;
|
|
319
|
+
return this
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async readable() {
|
|
323
|
+
this.simple();
|
|
324
|
+
this.streaming = true;
|
|
325
|
+
return this
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async writable() {
|
|
329
|
+
this.simple();
|
|
330
|
+
this.streaming = true;
|
|
331
|
+
return this
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
cursor(rows = 1, fn) {
|
|
335
|
+
this.options.simple = false;
|
|
336
|
+
if (typeof rows === 'function') {
|
|
337
|
+
fn = rows;
|
|
338
|
+
rows = 1;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
this.cursorRows = rows;
|
|
342
|
+
|
|
343
|
+
if (typeof fn === 'function')
|
|
344
|
+
return (this.cursorFn = fn, this)
|
|
345
|
+
|
|
346
|
+
let prev;
|
|
347
|
+
return {
|
|
348
|
+
[Symbol.asyncIterator]: () => ({
|
|
349
|
+
next: () => {
|
|
350
|
+
if (this.executed && !this.active)
|
|
351
|
+
return { done: true }
|
|
352
|
+
|
|
353
|
+
prev && prev();
|
|
354
|
+
const promise = new Promise((resolve, reject) => {
|
|
355
|
+
this.cursorFn = value => {
|
|
356
|
+
resolve({ value, done: false });
|
|
357
|
+
return new Promise(r => prev = r)
|
|
358
|
+
};
|
|
359
|
+
this.resolve = () => (this.active = false, resolve({ done: true }));
|
|
360
|
+
this.reject = x => (this.active = false, reject(x));
|
|
361
|
+
});
|
|
362
|
+
this.execute();
|
|
363
|
+
return promise
|
|
364
|
+
},
|
|
365
|
+
return() {
|
|
366
|
+
prev && prev(CLOSE);
|
|
367
|
+
return { done: true }
|
|
368
|
+
}
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
describe() {
|
|
374
|
+
this.options.simple = false;
|
|
375
|
+
this.onlyDescribe = this.options.prepare = true;
|
|
376
|
+
return this
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
stream() {
|
|
380
|
+
throw new Error('.stream has been renamed to .forEach')
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
forEach(fn) {
|
|
384
|
+
this.forEachFn = fn;
|
|
385
|
+
this.handle();
|
|
386
|
+
return this
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
raw() {
|
|
390
|
+
this.isRaw = true;
|
|
391
|
+
return this
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
values() {
|
|
395
|
+
this.isRaw = 'values';
|
|
396
|
+
return this
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
async handle() {
|
|
400
|
+
!this.executed && (this.executed = true) && await 1 && this.handler(this);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
execute() {
|
|
404
|
+
this.handle();
|
|
405
|
+
return this
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
then() {
|
|
409
|
+
this.handle();
|
|
410
|
+
return super.then.apply(this, arguments)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
catch() {
|
|
414
|
+
this.handle();
|
|
415
|
+
return super.catch.apply(this, arguments)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
finally() {
|
|
419
|
+
this.handle();
|
|
420
|
+
return super.finally.apply(this, arguments)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function cachedError(xs) {
|
|
425
|
+
if (originCache.has(xs))
|
|
426
|
+
return originCache.get(xs)
|
|
427
|
+
|
|
428
|
+
const x = Error.stackTraceLimit;
|
|
429
|
+
Error.stackTraceLimit = 4;
|
|
430
|
+
originCache.set(xs, new Error());
|
|
431
|
+
Error.stackTraceLimit = x;
|
|
432
|
+
return originCache.get(xs)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
class PostgresError extends Error {
|
|
436
|
+
constructor(x) {
|
|
437
|
+
super(x.message);
|
|
438
|
+
this.name = this.constructor.name;
|
|
439
|
+
Object.assign(this, x);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const Errors = {
|
|
444
|
+
connection,
|
|
445
|
+
postgres,
|
|
446
|
+
generic,
|
|
447
|
+
notSupported
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
function connection(x, options, socket) {
|
|
451
|
+
const { host, port } = socket || options;
|
|
452
|
+
const error = Object.assign(
|
|
453
|
+
new Error(('write ' + x + ' ' + (options.path || (host + ':' + port)))),
|
|
454
|
+
{
|
|
455
|
+
code: x,
|
|
456
|
+
errno: x,
|
|
457
|
+
address: options.path || host
|
|
458
|
+
}, options.path ? {} : { port: port }
|
|
459
|
+
);
|
|
460
|
+
Error.captureStackTrace(error, connection);
|
|
461
|
+
return error
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function postgres(x) {
|
|
465
|
+
const error = new PostgresError(x);
|
|
466
|
+
Error.captureStackTrace(error, postgres);
|
|
467
|
+
return error
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function generic(code, message) {
|
|
471
|
+
const error = Object.assign(new Error(code + ': ' + message), { code });
|
|
472
|
+
Error.captureStackTrace(error, generic);
|
|
473
|
+
return error
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* c8 ignore next 10 */
|
|
477
|
+
function notSupported(x) {
|
|
478
|
+
const error = Object.assign(
|
|
479
|
+
new Error(x + ' (B) is not supported'),
|
|
480
|
+
{
|
|
481
|
+
code: 'MESSAGE_NOT_SUPPORTED',
|
|
482
|
+
name: x
|
|
483
|
+
}
|
|
484
|
+
);
|
|
485
|
+
Error.captureStackTrace(error, notSupported);
|
|
486
|
+
return error
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const types = {
|
|
490
|
+
string: {
|
|
491
|
+
to: 25,
|
|
492
|
+
from: null, // defaults to string
|
|
493
|
+
serialize: x => '' + x
|
|
494
|
+
},
|
|
495
|
+
number: {
|
|
496
|
+
to: 0,
|
|
497
|
+
from: [21, 23, 26, 700, 701],
|
|
498
|
+
serialize: x => '' + x,
|
|
499
|
+
parse: x => +x
|
|
500
|
+
},
|
|
501
|
+
json: {
|
|
502
|
+
to: 114,
|
|
503
|
+
from: [114, 3802],
|
|
504
|
+
serialize: x => JSON.stringify(x),
|
|
505
|
+
parse: x => JSON.parse(x)
|
|
506
|
+
},
|
|
507
|
+
boolean: {
|
|
508
|
+
to: 16,
|
|
509
|
+
from: 16,
|
|
510
|
+
serialize: x => x === true ? 't' : 'f',
|
|
511
|
+
parse: x => x === 't'
|
|
512
|
+
},
|
|
513
|
+
date: {
|
|
514
|
+
to: 1184,
|
|
515
|
+
from: [1082, 1114, 1184],
|
|
516
|
+
serialize: x => (x instanceof Date ? x : new Date(x)).toISOString(),
|
|
517
|
+
parse: x => new Date(x)
|
|
518
|
+
},
|
|
519
|
+
bytea: {
|
|
520
|
+
to: 17,
|
|
521
|
+
from: 17,
|
|
522
|
+
serialize: x => '\\x' + Buffer.from(x).toString('hex'),
|
|
523
|
+
parse: x => Buffer.from(x.slice(2), 'hex')
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
class NotTagged { then() { notTagged(); } catch() { notTagged(); } finally() { notTagged(); }}
|
|
528
|
+
|
|
529
|
+
class Identifier extends NotTagged {
|
|
530
|
+
constructor(value) {
|
|
531
|
+
super();
|
|
532
|
+
this.value = escapeIdentifier(value);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
class Parameter extends NotTagged {
|
|
537
|
+
constructor(value, type, array) {
|
|
538
|
+
super();
|
|
539
|
+
this.value = value;
|
|
540
|
+
this.type = type;
|
|
541
|
+
this.array = array;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
class Builder extends NotTagged {
|
|
546
|
+
constructor(first, rest) {
|
|
547
|
+
super();
|
|
548
|
+
this.first = first;
|
|
549
|
+
this.rest = rest;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
build(before, parameters, types, options) {
|
|
553
|
+
const keyword = builders.map(([x, fn]) => ({ fn, i: before.search(x) })).sort((a, b) => a.i - b.i).pop();
|
|
554
|
+
return keyword.i === -1
|
|
555
|
+
? escapeIdentifiers(this.first, options)
|
|
556
|
+
: keyword.fn(this.first, this.rest, parameters, types, options)
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
function handleValue(x, parameters, types, options) {
|
|
561
|
+
let value = x instanceof Parameter ? x.value : x;
|
|
562
|
+
if (value === undefined) {
|
|
563
|
+
x instanceof Parameter
|
|
564
|
+
? x.value = options.transform.undefined
|
|
565
|
+
: value = x = options.transform.undefined;
|
|
566
|
+
|
|
567
|
+
if (value === undefined)
|
|
568
|
+
throw Errors.generic('UNDEFINED_VALUE', 'Undefined values are not allowed')
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return '$' + (types.push(
|
|
572
|
+
x instanceof Parameter
|
|
573
|
+
? (parameters.push(x.value), x.array
|
|
574
|
+
? x.array[x.type || inferType(x.value)] || x.type || firstIsString(x.value)
|
|
575
|
+
: x.type
|
|
576
|
+
)
|
|
577
|
+
: (parameters.push(x), inferType(x))
|
|
578
|
+
))
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const defaultHandlers = typeHandlers(types);
|
|
582
|
+
|
|
583
|
+
function stringify(q, string, value, parameters, types, options) { // eslint-disable-line
|
|
584
|
+
for (let i = 1; i < q.strings.length; i++) {
|
|
585
|
+
string += (stringifyValue(string, value, parameters, types, options)) + q.strings[i];
|
|
586
|
+
value = q.args[i];
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return string
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
function stringifyValue(string, value, parameters, types, o) {
|
|
593
|
+
return (
|
|
594
|
+
value instanceof Builder ? value.build(string, parameters, types, o) :
|
|
595
|
+
value instanceof Query ? fragment(value, parameters, types, o) :
|
|
596
|
+
value instanceof Identifier ? value.value :
|
|
597
|
+
value && value[0] instanceof Query ? value.reduce((acc, x) => acc + ' ' + fragment(x, parameters, types, o), '') :
|
|
598
|
+
handleValue(value, parameters, types, o)
|
|
599
|
+
)
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function fragment(q, parameters, types, options) {
|
|
603
|
+
q.fragment = true;
|
|
604
|
+
return stringify(q, q.strings[0], q.args[0], parameters, types, options)
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function valuesBuilder(first, parameters, types, columns, options) {
|
|
608
|
+
return first.map(row =>
|
|
609
|
+
'(' + columns.map(column =>
|
|
610
|
+
stringifyValue('values', row[column], parameters, types, options)
|
|
611
|
+
).join(',') + ')'
|
|
612
|
+
).join(',')
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function values(first, rest, parameters, types, options) {
|
|
616
|
+
const multi = Array.isArray(first[0]);
|
|
617
|
+
const columns = rest.length ? rest.flat() : Object.keys(multi ? first[0] : first);
|
|
618
|
+
return valuesBuilder(multi ? first : [first], parameters, types, columns, options)
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function select(first, rest, parameters, types, options) {
|
|
622
|
+
typeof first === 'string' && (first = [first].concat(rest));
|
|
623
|
+
if (Array.isArray(first))
|
|
624
|
+
return escapeIdentifiers(first, options)
|
|
625
|
+
|
|
626
|
+
let value;
|
|
627
|
+
const columns = rest.length ? rest.flat() : Object.keys(first);
|
|
628
|
+
return columns.map(x => {
|
|
629
|
+
value = first[x];
|
|
630
|
+
return (
|
|
631
|
+
value instanceof Query ? fragment(value, parameters, types, options) :
|
|
632
|
+
value instanceof Identifier ? value.value :
|
|
633
|
+
handleValue(value, parameters, types, options)
|
|
634
|
+
) + ' as ' + escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x)
|
|
635
|
+
}).join(',')
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const builders = Object.entries({
|
|
639
|
+
values,
|
|
640
|
+
in: (...xs) => {
|
|
641
|
+
const x = values(...xs);
|
|
642
|
+
return x === '()' ? '(null)' : x
|
|
643
|
+
},
|
|
644
|
+
select,
|
|
645
|
+
as: select,
|
|
646
|
+
returning: select,
|
|
647
|
+
'\\(': select,
|
|
648
|
+
|
|
649
|
+
update(first, rest, parameters, types, options) {
|
|
650
|
+
return (rest.length ? rest.flat() : Object.keys(first)).map(x =>
|
|
651
|
+
escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x) +
|
|
652
|
+
'=' + stringifyValue('values', first[x], parameters, types, options)
|
|
653
|
+
)
|
|
654
|
+
},
|
|
655
|
+
|
|
656
|
+
insert(first, rest, parameters, types, options) {
|
|
657
|
+
const columns = rest.length ? rest.flat() : Object.keys(Array.isArray(first) ? first[0] : first);
|
|
658
|
+
return '(' + escapeIdentifiers(columns, options) + ')values' +
|
|
659
|
+
valuesBuilder(Array.isArray(first) ? first : [first], parameters, types, columns, options)
|
|
660
|
+
}
|
|
661
|
+
}).map(([x, fn]) => ([new RegExp('((?:^|[\\s(])' + x + '(?:$|[\\s(]))(?![\\s\\S]*\\1)', 'i'), fn]));
|
|
662
|
+
|
|
663
|
+
function notTagged() {
|
|
664
|
+
throw Errors.generic('NOT_TAGGED_CALL', 'Query not called as a tagged template literal')
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const serializers = defaultHandlers.serializers;
|
|
668
|
+
const parsers = defaultHandlers.parsers;
|
|
669
|
+
|
|
670
|
+
function firstIsString(x) {
|
|
671
|
+
if (Array.isArray(x))
|
|
672
|
+
return firstIsString(x[0])
|
|
673
|
+
return typeof x === 'string' ? 1009 : 0
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const mergeUserTypes = function(types) {
|
|
677
|
+
const user = typeHandlers(types || {});
|
|
678
|
+
return {
|
|
679
|
+
serializers: Object.assign({}, serializers, user.serializers),
|
|
680
|
+
parsers: Object.assign({}, parsers, user.parsers)
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
function typeHandlers(types) {
|
|
685
|
+
return Object.keys(types).reduce((acc, k) => {
|
|
686
|
+
types[k].from && [].concat(types[k].from).forEach(x => acc.parsers[x] = types[k].parse);
|
|
687
|
+
if (types[k].serialize) {
|
|
688
|
+
acc.serializers[types[k].to] = types[k].serialize;
|
|
689
|
+
types[k].from && [].concat(types[k].from).forEach(x => acc.serializers[x] = types[k].serialize);
|
|
690
|
+
}
|
|
691
|
+
return acc
|
|
692
|
+
}, { parsers: {}, serializers: {} })
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function escapeIdentifiers(xs, { transform: { column } }) {
|
|
696
|
+
return xs.map(x => escapeIdentifier(column.to ? column.to(x) : x)).join(',')
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const escapeIdentifier = function escape(str) {
|
|
700
|
+
return '"' + str.replace(/"/g, '""').replace(/\./g, '"."') + '"'
|
|
701
|
+
};
|
|
702
|
+
|
|
703
|
+
const inferType = function inferType(x) {
|
|
704
|
+
return (
|
|
705
|
+
x instanceof Parameter ? x.type :
|
|
706
|
+
x instanceof Date ? 1184 :
|
|
707
|
+
x instanceof Uint8Array ? 17 :
|
|
708
|
+
(x === true || x === false) ? 16 :
|
|
709
|
+
typeof x === 'bigint' ? 20 :
|
|
710
|
+
Array.isArray(x) ? inferType(x[0]) :
|
|
711
|
+
0
|
|
712
|
+
)
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
const escapeBackslash = /\\/g;
|
|
716
|
+
const escapeQuote = /"/g;
|
|
717
|
+
|
|
718
|
+
function arrayEscape(x) {
|
|
719
|
+
return x
|
|
720
|
+
.replace(escapeBackslash, '\\\\')
|
|
721
|
+
.replace(escapeQuote, '\\"')
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const arraySerializer = function arraySerializer(xs, serializer, options, typarray) {
|
|
725
|
+
if (Array.isArray(xs) === false)
|
|
726
|
+
return xs
|
|
727
|
+
|
|
728
|
+
if (!xs.length)
|
|
729
|
+
return '{}'
|
|
730
|
+
|
|
731
|
+
const first = xs[0];
|
|
732
|
+
// Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter
|
|
733
|
+
const delimiter = typarray === 1020 ? ';' : ',';
|
|
734
|
+
|
|
735
|
+
if (Array.isArray(first) && !first.type)
|
|
736
|
+
return '{' + xs.map(x => arraySerializer(x, serializer, options, typarray)).join(delimiter) + '}'
|
|
737
|
+
|
|
738
|
+
return '{' + xs.map(x => {
|
|
739
|
+
if (x === undefined) {
|
|
740
|
+
x = options.transform.undefined;
|
|
741
|
+
if (x === undefined)
|
|
742
|
+
throw Errors.generic('UNDEFINED_VALUE', 'Undefined values are not allowed')
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return x === null
|
|
746
|
+
? 'null'
|
|
747
|
+
: '"' + arrayEscape(serializer ? serializer(x.type ? x.value : x) : '' + x) + '"'
|
|
748
|
+
}).join(delimiter) + '}'
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
const arrayParserState = {
|
|
752
|
+
i: 0,
|
|
753
|
+
char: null,
|
|
754
|
+
str: '',
|
|
755
|
+
quoted: false,
|
|
756
|
+
last: 0
|
|
757
|
+
};
|
|
758
|
+
|
|
759
|
+
const arrayParser = function arrayParser(x, parser, typarray) {
|
|
760
|
+
arrayParserState.i = arrayParserState.last = 0;
|
|
761
|
+
return arrayParserLoop(arrayParserState, x, parser, typarray)
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
function arrayParserLoop(s, x, parser, typarray) {
|
|
765
|
+
const xs = [];
|
|
766
|
+
// Only _box (1020) has the ';' delimiter for arrays, all other types use the ',' delimiter
|
|
767
|
+
const delimiter = typarray === 1020 ? ';' : ',';
|
|
768
|
+
for (; s.i < x.length; s.i++) {
|
|
769
|
+
s.char = x[s.i];
|
|
770
|
+
if (s.quoted) {
|
|
771
|
+
if (s.char === '\\') {
|
|
772
|
+
s.str += x[++s.i];
|
|
773
|
+
} else if (s.char === '"') {
|
|
774
|
+
xs.push(parser ? parser(s.str) : s.str);
|
|
775
|
+
s.str = '';
|
|
776
|
+
s.quoted = x[s.i + 1] === '"';
|
|
777
|
+
s.last = s.i + 2;
|
|
778
|
+
} else {
|
|
779
|
+
s.str += s.char;
|
|
780
|
+
}
|
|
781
|
+
} else if (s.char === '"') {
|
|
782
|
+
s.quoted = true;
|
|
783
|
+
} else if (s.char === '{') {
|
|
784
|
+
s.last = ++s.i;
|
|
785
|
+
xs.push(arrayParserLoop(s, x, parser, typarray));
|
|
786
|
+
} else if (s.char === '}') {
|
|
787
|
+
s.quoted = false;
|
|
788
|
+
s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i));
|
|
789
|
+
s.last = s.i + 1;
|
|
790
|
+
break
|
|
791
|
+
} else if (s.char === delimiter && s.p !== '}' && s.p !== '"') {
|
|
792
|
+
xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i));
|
|
793
|
+
s.last = s.i + 1;
|
|
794
|
+
}
|
|
795
|
+
s.p = s.char;
|
|
796
|
+
}
|
|
797
|
+
s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i + 1)) : x.slice(s.last, s.i + 1));
|
|
798
|
+
return xs
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
const toCamel = x => {
|
|
802
|
+
let str = x[0];
|
|
803
|
+
for (let i = 1; i < x.length; i++)
|
|
804
|
+
str += x[i] === '_' ? x[++i].toUpperCase() : x[i];
|
|
805
|
+
return str
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
const toPascal = x => {
|
|
809
|
+
let str = x[0].toUpperCase();
|
|
810
|
+
for (let i = 1; i < x.length; i++)
|
|
811
|
+
str += x[i] === '_' ? x[++i].toUpperCase() : x[i];
|
|
812
|
+
return str
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
const toKebab = x => x.replace(/_/g, '-');
|
|
816
|
+
|
|
817
|
+
const fromCamel = x => x.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
818
|
+
const fromPascal = x => (x.slice(0, 1) + x.slice(1).replace(/([A-Z])/g, '_$1')).toLowerCase();
|
|
819
|
+
const fromKebab = x => x.replace(/-/g, '_');
|
|
820
|
+
|
|
821
|
+
function createJsonTransform(fn) {
|
|
822
|
+
return function jsonTransform(x, column) {
|
|
823
|
+
return typeof x === 'object' && x !== null && (column.type === 114 || column.type === 3802)
|
|
824
|
+
? Array.isArray(x)
|
|
825
|
+
? x.map(x => jsonTransform(x, column))
|
|
826
|
+
: Object.entries(x).reduce((acc, [k, v]) => Object.assign(acc, { [fn(k)]: jsonTransform(v, column) }), {})
|
|
827
|
+
: x
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
toCamel.column = { from: toCamel };
|
|
832
|
+
toCamel.value = { from: createJsonTransform(toCamel) };
|
|
833
|
+
fromCamel.column = { to: fromCamel };
|
|
834
|
+
|
|
835
|
+
const camel = { ...toCamel };
|
|
836
|
+
camel.column.to = fromCamel;
|
|
837
|
+
|
|
838
|
+
toPascal.column = { from: toPascal };
|
|
839
|
+
toPascal.value = { from: createJsonTransform(toPascal) };
|
|
840
|
+
fromPascal.column = { to: fromPascal };
|
|
841
|
+
|
|
842
|
+
const pascal = { ...toPascal };
|
|
843
|
+
pascal.column.to = fromPascal;
|
|
844
|
+
|
|
845
|
+
toKebab.column = { from: toKebab };
|
|
846
|
+
toKebab.value = { from: createJsonTransform(toKebab) };
|
|
847
|
+
fromKebab.column = { to: fromKebab };
|
|
848
|
+
|
|
849
|
+
const kebab = { ...toKebab };
|
|
850
|
+
kebab.column.to = fromKebab;
|
|
851
|
+
|
|
852
|
+
class Result extends Array {
|
|
853
|
+
constructor() {
|
|
854
|
+
super();
|
|
855
|
+
Object.defineProperties(this, {
|
|
856
|
+
count: { value: null, writable: true },
|
|
857
|
+
state: { value: null, writable: true },
|
|
858
|
+
command: { value: null, writable: true },
|
|
859
|
+
columns: { value: null, writable: true },
|
|
860
|
+
statement: { value: null, writable: true }
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
static get [Symbol.species]() {
|
|
865
|
+
return Array
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
function Queue(initial = []) {
|
|
870
|
+
let xs = initial.slice();
|
|
871
|
+
let index = 0;
|
|
872
|
+
|
|
873
|
+
return {
|
|
874
|
+
get length() {
|
|
875
|
+
return xs.length - index
|
|
876
|
+
},
|
|
877
|
+
remove: (x) => {
|
|
878
|
+
const index = xs.indexOf(x);
|
|
879
|
+
return index === -1
|
|
880
|
+
? null
|
|
881
|
+
: (xs.splice(index, 1), x)
|
|
882
|
+
},
|
|
883
|
+
push: (x) => (xs.push(x), x),
|
|
884
|
+
shift: () => {
|
|
885
|
+
const out = xs[index++];
|
|
886
|
+
|
|
887
|
+
if (index === xs.length) {
|
|
888
|
+
index = 0;
|
|
889
|
+
xs = [];
|
|
890
|
+
} else {
|
|
891
|
+
xs[index - 1] = undefined;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
return out
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
const size = 256;
|
|
900
|
+
let buffer = Buffer.allocUnsafe(size);
|
|
901
|
+
|
|
902
|
+
const messages = 'BCcDdEFfHPpQSX'.split('').reduce((acc, x) => {
|
|
903
|
+
const v = x.charCodeAt(0);
|
|
904
|
+
acc[x] = () => {
|
|
905
|
+
buffer[0] = v;
|
|
906
|
+
b.i = 5;
|
|
907
|
+
return b
|
|
908
|
+
};
|
|
909
|
+
return acc
|
|
910
|
+
}, {});
|
|
911
|
+
|
|
912
|
+
const b = Object.assign(reset, messages, {
|
|
913
|
+
N: String.fromCharCode(0),
|
|
914
|
+
i: 0,
|
|
915
|
+
inc(x) {
|
|
916
|
+
b.i += x;
|
|
917
|
+
return b
|
|
918
|
+
},
|
|
919
|
+
str(x) {
|
|
920
|
+
const length = Buffer.byteLength(x);
|
|
921
|
+
fit(length);
|
|
922
|
+
b.i += buffer.write(x, b.i, length, 'utf8');
|
|
923
|
+
return b
|
|
924
|
+
},
|
|
925
|
+
i16(x) {
|
|
926
|
+
fit(2);
|
|
927
|
+
buffer.writeUInt16BE(x, b.i);
|
|
928
|
+
b.i += 2;
|
|
929
|
+
return b
|
|
930
|
+
},
|
|
931
|
+
i32(x, i) {
|
|
932
|
+
if (i || i === 0) {
|
|
933
|
+
buffer.writeUInt32BE(x, i);
|
|
934
|
+
return b
|
|
935
|
+
}
|
|
936
|
+
fit(4);
|
|
937
|
+
buffer.writeUInt32BE(x, b.i);
|
|
938
|
+
b.i += 4;
|
|
939
|
+
return b
|
|
940
|
+
},
|
|
941
|
+
z(x) {
|
|
942
|
+
fit(x);
|
|
943
|
+
buffer.fill(0, b.i, b.i + x);
|
|
944
|
+
b.i += x;
|
|
945
|
+
return b
|
|
946
|
+
},
|
|
947
|
+
raw(x) {
|
|
948
|
+
buffer = Buffer.concat([buffer.subarray(0, b.i), x]);
|
|
949
|
+
b.i = buffer.length;
|
|
950
|
+
return b
|
|
951
|
+
},
|
|
952
|
+
end(at = 1) {
|
|
953
|
+
buffer.writeUInt32BE(b.i - at, at);
|
|
954
|
+
const out = buffer.subarray(0, b.i);
|
|
955
|
+
b.i = 0;
|
|
956
|
+
buffer = Buffer.allocUnsafe(size);
|
|
957
|
+
return out
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
function fit(x) {
|
|
962
|
+
if (buffer.length - b.i < x) {
|
|
963
|
+
const prev = buffer
|
|
964
|
+
, length = prev.length;
|
|
965
|
+
|
|
966
|
+
buffer = Buffer.allocUnsafe(length + (length >> 1) + x);
|
|
967
|
+
prev.copy(buffer);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
function reset() {
|
|
972
|
+
b.i = 0;
|
|
973
|
+
return b
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
let uid = 1;
|
|
977
|
+
|
|
978
|
+
const Sync = b().S().end()
|
|
979
|
+
, Flush = b().H().end()
|
|
980
|
+
, SSLRequest = b().i32(8).i32(80877103).end(8)
|
|
981
|
+
, ExecuteUnnamed = Buffer.concat([b().E().str(b.N).i32(0).end(), Sync])
|
|
982
|
+
, DescribeUnnamed = b().D().str('S').str(b.N).end()
|
|
983
|
+
, noop$2 = () => { /* noop */ };
|
|
984
|
+
|
|
985
|
+
const retryRoutines = new Set([
|
|
986
|
+
'FetchPreparedStatement',
|
|
987
|
+
'RevalidateCachedQuery',
|
|
988
|
+
'transformAssignedExpr'
|
|
989
|
+
]);
|
|
990
|
+
|
|
991
|
+
const errorFields = {
|
|
992
|
+
83 : 'severity_local', // S
|
|
993
|
+
86 : 'severity', // V
|
|
994
|
+
67 : 'code', // C
|
|
995
|
+
77 : 'message', // M
|
|
996
|
+
68 : 'detail', // D
|
|
997
|
+
72 : 'hint', // H
|
|
998
|
+
80 : 'position', // P
|
|
999
|
+
112 : 'internal_position', // p
|
|
1000
|
+
113 : 'internal_query', // q
|
|
1001
|
+
87 : 'where', // W
|
|
1002
|
+
115 : 'schema_name', // s
|
|
1003
|
+
116 : 'table_name', // t
|
|
1004
|
+
99 : 'column_name', // c
|
|
1005
|
+
100 : 'data type_name', // d
|
|
1006
|
+
110 : 'constraint_name', // n
|
|
1007
|
+
70 : 'file', // F
|
|
1008
|
+
76 : 'line', // L
|
|
1009
|
+
82 : 'routine' // R
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
function Connection(options, queues = {}, { onopen = noop$2, onend = noop$2, onclose = noop$2 } = {}) {
|
|
1013
|
+
const {
|
|
1014
|
+
sslnegotiation,
|
|
1015
|
+
ssl,
|
|
1016
|
+
max,
|
|
1017
|
+
user,
|
|
1018
|
+
host,
|
|
1019
|
+
port,
|
|
1020
|
+
database,
|
|
1021
|
+
parsers,
|
|
1022
|
+
transform,
|
|
1023
|
+
onnotice,
|
|
1024
|
+
onnotify,
|
|
1025
|
+
onparameter,
|
|
1026
|
+
max_pipeline,
|
|
1027
|
+
keep_alive,
|
|
1028
|
+
backoff,
|
|
1029
|
+
target_session_attrs
|
|
1030
|
+
} = options;
|
|
1031
|
+
|
|
1032
|
+
const sent = Queue()
|
|
1033
|
+
, id = uid++
|
|
1034
|
+
, backend = { pid: null, secret: null }
|
|
1035
|
+
, idleTimer = timer(end, options.idle_timeout)
|
|
1036
|
+
, lifeTimer = timer(end, options.max_lifetime)
|
|
1037
|
+
, connectTimer = timer(connectTimedOut, options.connect_timeout);
|
|
1038
|
+
|
|
1039
|
+
let socket = null
|
|
1040
|
+
, cancelMessage
|
|
1041
|
+
, errorResponse = null
|
|
1042
|
+
, result = new Result()
|
|
1043
|
+
, incoming = Buffer.alloc(0)
|
|
1044
|
+
, needsTypes = options.fetch_types
|
|
1045
|
+
, backendParameters = {}
|
|
1046
|
+
, statements = {}
|
|
1047
|
+
, statementId = Math.random().toString(36).slice(2)
|
|
1048
|
+
, statementCount = 1
|
|
1049
|
+
, closedTime = 0
|
|
1050
|
+
, remaining = 0
|
|
1051
|
+
, hostIndex = 0
|
|
1052
|
+
, retries = 0
|
|
1053
|
+
, length = 0
|
|
1054
|
+
, delay = 0
|
|
1055
|
+
, rows = 0
|
|
1056
|
+
, serverSignature = null
|
|
1057
|
+
, nextWriteTimer = null
|
|
1058
|
+
, terminated = false
|
|
1059
|
+
, incomings = null
|
|
1060
|
+
, results = null
|
|
1061
|
+
, initial = null
|
|
1062
|
+
, ending = null
|
|
1063
|
+
, stream = null
|
|
1064
|
+
, chunk = null
|
|
1065
|
+
, ended = null
|
|
1066
|
+
, nonce = null
|
|
1067
|
+
, query = null
|
|
1068
|
+
, final = null;
|
|
1069
|
+
|
|
1070
|
+
const connection = {
|
|
1071
|
+
queue: queues.closed,
|
|
1072
|
+
idleTimer,
|
|
1073
|
+
connect(query) {
|
|
1074
|
+
initial = query;
|
|
1075
|
+
reconnect();
|
|
1076
|
+
},
|
|
1077
|
+
terminate,
|
|
1078
|
+
execute,
|
|
1079
|
+
cancel,
|
|
1080
|
+
end,
|
|
1081
|
+
count: 0,
|
|
1082
|
+
id
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
queues.closed && queues.closed.push(connection);
|
|
1086
|
+
|
|
1087
|
+
return connection
|
|
1088
|
+
|
|
1089
|
+
async function createSocket() {
|
|
1090
|
+
let x;
|
|
1091
|
+
try {
|
|
1092
|
+
x = options.socket
|
|
1093
|
+
? (await Promise.resolve(options.socket(options)))
|
|
1094
|
+
: new net.Socket();
|
|
1095
|
+
} catch (e) {
|
|
1096
|
+
error(e);
|
|
1097
|
+
return
|
|
1098
|
+
}
|
|
1099
|
+
x.on('error', error);
|
|
1100
|
+
x.on('close', closed);
|
|
1101
|
+
x.on('drain', drain);
|
|
1102
|
+
return x
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
async function cancel({ pid, secret }, resolve, reject) {
|
|
1106
|
+
try {
|
|
1107
|
+
cancelMessage = b().i32(16).i32(80877102).i32(pid).i32(secret).end(16);
|
|
1108
|
+
await connect();
|
|
1109
|
+
socket.once('error', reject);
|
|
1110
|
+
socket.once('close', resolve);
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
reject(error);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
function execute(q) {
|
|
1117
|
+
if (terminated)
|
|
1118
|
+
return queryError(q, Errors.connection('CONNECTION_DESTROYED', options))
|
|
1119
|
+
|
|
1120
|
+
if (stream)
|
|
1121
|
+
return queryError(q, Errors.generic('COPY_IN_PROGRESS', 'You cannot execute queries during copy'))
|
|
1122
|
+
|
|
1123
|
+
if (q.cancelled)
|
|
1124
|
+
return
|
|
1125
|
+
|
|
1126
|
+
try {
|
|
1127
|
+
q.state = backend;
|
|
1128
|
+
query
|
|
1129
|
+
? sent.push(q)
|
|
1130
|
+
: (query = q, query.active = true);
|
|
1131
|
+
|
|
1132
|
+
build(q);
|
|
1133
|
+
return write(toBuffer(q))
|
|
1134
|
+
&& !q.describeFirst
|
|
1135
|
+
&& !q.cursorFn
|
|
1136
|
+
&& sent.length < max_pipeline
|
|
1137
|
+
&& (!q.options.onexecute || q.options.onexecute(connection))
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
sent.length === 0 && write(Sync);
|
|
1140
|
+
errored(error);
|
|
1141
|
+
return true
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function toBuffer(q) {
|
|
1146
|
+
if (q.parameters.length >= 65534)
|
|
1147
|
+
throw Errors.generic('MAX_PARAMETERS_EXCEEDED', 'Max number of parameters (65534) exceeded')
|
|
1148
|
+
|
|
1149
|
+
return q.options.simple
|
|
1150
|
+
? b().Q().str(q.statement.string + b.N).end()
|
|
1151
|
+
: q.describeFirst
|
|
1152
|
+
? Buffer.concat([describe(q), Flush])
|
|
1153
|
+
: q.prepare
|
|
1154
|
+
? q.prepared
|
|
1155
|
+
? prepared(q)
|
|
1156
|
+
: Buffer.concat([describe(q), prepared(q)])
|
|
1157
|
+
: unnamed(q)
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
function describe(q) {
|
|
1161
|
+
return Buffer.concat([
|
|
1162
|
+
Parse(q.statement.string, q.parameters, q.statement.types, q.statement.name),
|
|
1163
|
+
Describe('S', q.statement.name)
|
|
1164
|
+
])
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
function prepared(q) {
|
|
1168
|
+
return Buffer.concat([
|
|
1169
|
+
Bind(q.parameters, q.statement.types, q.statement.name, q.cursorName),
|
|
1170
|
+
q.cursorFn
|
|
1171
|
+
? Execute('', q.cursorRows)
|
|
1172
|
+
: ExecuteUnnamed
|
|
1173
|
+
])
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
function unnamed(q) {
|
|
1177
|
+
return Buffer.concat([
|
|
1178
|
+
Parse(q.statement.string, q.parameters, q.statement.types),
|
|
1179
|
+
DescribeUnnamed,
|
|
1180
|
+
prepared(q)
|
|
1181
|
+
])
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
function build(q) {
|
|
1185
|
+
const parameters = []
|
|
1186
|
+
, types = [];
|
|
1187
|
+
|
|
1188
|
+
const string = stringify(q, q.strings[0], q.args[0], parameters, types, options);
|
|
1189
|
+
|
|
1190
|
+
!q.tagged && q.args.forEach(x => handleValue(x, parameters, types, options));
|
|
1191
|
+
|
|
1192
|
+
q.prepare = options.prepare && ('prepare' in q.options ? q.options.prepare : true);
|
|
1193
|
+
q.string = string;
|
|
1194
|
+
q.signature = q.prepare && types + string;
|
|
1195
|
+
q.onlyDescribe && (delete statements[q.signature]);
|
|
1196
|
+
q.parameters = q.parameters || parameters;
|
|
1197
|
+
q.prepared = q.prepare && q.signature in statements;
|
|
1198
|
+
q.describeFirst = q.onlyDescribe || (parameters.length && !q.prepared);
|
|
1199
|
+
q.statement = q.prepared
|
|
1200
|
+
? statements[q.signature]
|
|
1201
|
+
: { string, types, name: q.prepare ? statementId + statementCount++ : '' };
|
|
1202
|
+
|
|
1203
|
+
typeof options.debug === 'function' && options.debug(id, string, parameters, types);
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
function write(x, fn) {
|
|
1207
|
+
chunk = chunk ? Buffer.concat([chunk, x]) : Buffer.from(x);
|
|
1208
|
+
if (chunk.length >= 1024)
|
|
1209
|
+
return nextWrite(fn)
|
|
1210
|
+
nextWriteTimer === null && (nextWriteTimer = setImmediate(nextWrite));
|
|
1211
|
+
return true
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
function nextWrite(fn) {
|
|
1215
|
+
const x = socket.write(chunk, fn);
|
|
1216
|
+
nextWriteTimer !== null && clearImmediate(nextWriteTimer);
|
|
1217
|
+
chunk = nextWriteTimer = null;
|
|
1218
|
+
return x
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
function connectTimedOut() {
|
|
1222
|
+
errored(Errors.connection('CONNECT_TIMEOUT', options, socket));
|
|
1223
|
+
socket.destroy();
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
async function secure() {
|
|
1227
|
+
if (sslnegotiation !== 'direct') {
|
|
1228
|
+
write(SSLRequest);
|
|
1229
|
+
const canSSL = await new Promise(r => socket.once('data', x => r(x[0] === 83))); // S
|
|
1230
|
+
|
|
1231
|
+
if (!canSSL && ssl === 'prefer')
|
|
1232
|
+
return connected()
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
const options = {
|
|
1236
|
+
socket,
|
|
1237
|
+
servername: net.isIP(socket.host) ? undefined : socket.host
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
if (sslnegotiation === 'direct')
|
|
1241
|
+
options.ALPNProtocols = ['postgresql'];
|
|
1242
|
+
|
|
1243
|
+
if (ssl === 'require' || ssl === 'allow' || ssl === 'prefer')
|
|
1244
|
+
options.rejectUnauthorized = false;
|
|
1245
|
+
else if (typeof ssl === 'object')
|
|
1246
|
+
Object.assign(options, ssl);
|
|
1247
|
+
|
|
1248
|
+
socket.removeAllListeners();
|
|
1249
|
+
socket = tls.connect(options);
|
|
1250
|
+
socket.on('secureConnect', connected);
|
|
1251
|
+
socket.on('error', error);
|
|
1252
|
+
socket.on('close', closed);
|
|
1253
|
+
socket.on('drain', drain);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
/* c8 ignore next 3 */
|
|
1257
|
+
function drain() {
|
|
1258
|
+
!query && onopen(connection);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
function data(x) {
|
|
1262
|
+
if (incomings) {
|
|
1263
|
+
incomings.push(x);
|
|
1264
|
+
remaining -= x.length;
|
|
1265
|
+
if (remaining > 0)
|
|
1266
|
+
return
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
incoming = incomings
|
|
1270
|
+
? Buffer.concat(incomings, length - remaining)
|
|
1271
|
+
: incoming.length === 0
|
|
1272
|
+
? x
|
|
1273
|
+
: Buffer.concat([incoming, x], incoming.length + x.length);
|
|
1274
|
+
|
|
1275
|
+
while (incoming.length > 4) {
|
|
1276
|
+
length = incoming.readUInt32BE(1);
|
|
1277
|
+
if (length >= incoming.length) {
|
|
1278
|
+
remaining = length - incoming.length;
|
|
1279
|
+
incomings = [incoming];
|
|
1280
|
+
break
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
try {
|
|
1284
|
+
handle(incoming.subarray(0, length + 1));
|
|
1285
|
+
} catch (e) {
|
|
1286
|
+
query && (query.cursorFn || query.describeFirst) && write(Sync);
|
|
1287
|
+
errored(e);
|
|
1288
|
+
}
|
|
1289
|
+
incoming = incoming.subarray(length + 1);
|
|
1290
|
+
remaining = 0;
|
|
1291
|
+
incomings = null;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
async function connect() {
|
|
1296
|
+
terminated = false;
|
|
1297
|
+
backendParameters = {};
|
|
1298
|
+
socket || (socket = await createSocket());
|
|
1299
|
+
|
|
1300
|
+
if (!socket)
|
|
1301
|
+
return
|
|
1302
|
+
|
|
1303
|
+
connectTimer.start();
|
|
1304
|
+
|
|
1305
|
+
if (options.socket)
|
|
1306
|
+
return ssl ? secure() : connected()
|
|
1307
|
+
|
|
1308
|
+
socket.on('connect', ssl ? secure : connected);
|
|
1309
|
+
|
|
1310
|
+
if (options.path)
|
|
1311
|
+
return socket.connect(options.path)
|
|
1312
|
+
|
|
1313
|
+
socket.ssl = ssl;
|
|
1314
|
+
socket.connect(port[hostIndex], host[hostIndex]);
|
|
1315
|
+
socket.host = host[hostIndex];
|
|
1316
|
+
socket.port = port[hostIndex];
|
|
1317
|
+
|
|
1318
|
+
hostIndex = (hostIndex + 1) % port.length;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
function reconnect() {
|
|
1322
|
+
setTimeout(connect, closedTime ? Math.max(0, closedTime + delay - performance$1.now()) : 0);
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
function connected() {
|
|
1326
|
+
try {
|
|
1327
|
+
statements = {};
|
|
1328
|
+
needsTypes = options.fetch_types;
|
|
1329
|
+
statementId = Math.random().toString(36).slice(2);
|
|
1330
|
+
statementCount = 1;
|
|
1331
|
+
lifeTimer.start();
|
|
1332
|
+
socket.on('data', data);
|
|
1333
|
+
keep_alive && socket.setKeepAlive && socket.setKeepAlive(true, 1000 * keep_alive);
|
|
1334
|
+
const s = StartupMessage();
|
|
1335
|
+
write(s);
|
|
1336
|
+
} catch (err) {
|
|
1337
|
+
error(err);
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
function error(err) {
|
|
1342
|
+
if (connection.queue === queues.connecting && options.host[retries + 1])
|
|
1343
|
+
return
|
|
1344
|
+
|
|
1345
|
+
errored(err);
|
|
1346
|
+
while (sent.length)
|
|
1347
|
+
queryError(sent.shift(), err);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
function errored(err) {
|
|
1351
|
+
stream && (stream.destroy(err), stream = null);
|
|
1352
|
+
query && queryError(query, err);
|
|
1353
|
+
initial && (queryError(initial, err), initial = null);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
function queryError(query, err) {
|
|
1357
|
+
if (query.reserve)
|
|
1358
|
+
return query.reject(err)
|
|
1359
|
+
|
|
1360
|
+
if (!err || typeof err !== 'object')
|
|
1361
|
+
err = new Error(err);
|
|
1362
|
+
|
|
1363
|
+
'query' in err || 'parameters' in err || Object.defineProperties(err, {
|
|
1364
|
+
stack: { value: err.stack + query.origin.replace(/.*\n/, '\n'), enumerable: options.debug },
|
|
1365
|
+
query: { value: query.string, enumerable: options.debug },
|
|
1366
|
+
parameters: { value: query.parameters, enumerable: options.debug },
|
|
1367
|
+
args: { value: query.args, enumerable: options.debug },
|
|
1368
|
+
types: { value: query.statement && query.statement.types, enumerable: options.debug }
|
|
1369
|
+
});
|
|
1370
|
+
query.reject(err);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
function end() {
|
|
1374
|
+
return ending || (
|
|
1375
|
+
!connection.reserved && onend(connection),
|
|
1376
|
+
!connection.reserved && !initial && !query && sent.length === 0
|
|
1377
|
+
? (terminate(), new Promise(r => socket && socket.readyState !== 'closed' ? socket.once('close', r) : r()))
|
|
1378
|
+
: ending = new Promise(r => ended = r)
|
|
1379
|
+
)
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
function terminate() {
|
|
1383
|
+
terminated = true;
|
|
1384
|
+
if (stream || query || initial || sent.length)
|
|
1385
|
+
error(Errors.connection('CONNECTION_DESTROYED', options));
|
|
1386
|
+
|
|
1387
|
+
clearImmediate(nextWriteTimer);
|
|
1388
|
+
if (socket) {
|
|
1389
|
+
socket.removeListener('data', data);
|
|
1390
|
+
socket.removeListener('connect', connected);
|
|
1391
|
+
socket.readyState === 'open' && socket.end(b().X().end());
|
|
1392
|
+
}
|
|
1393
|
+
ended && (ended(), ending = ended = null);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
async function closed(hadError) {
|
|
1397
|
+
incoming = Buffer.alloc(0);
|
|
1398
|
+
remaining = 0;
|
|
1399
|
+
incomings = null;
|
|
1400
|
+
clearImmediate(nextWriteTimer);
|
|
1401
|
+
socket.removeListener('data', data);
|
|
1402
|
+
socket.removeListener('connect', connected);
|
|
1403
|
+
idleTimer.cancel();
|
|
1404
|
+
lifeTimer.cancel();
|
|
1405
|
+
connectTimer.cancel();
|
|
1406
|
+
|
|
1407
|
+
socket.removeAllListeners();
|
|
1408
|
+
socket = null;
|
|
1409
|
+
|
|
1410
|
+
if (initial)
|
|
1411
|
+
return reconnect()
|
|
1412
|
+
|
|
1413
|
+
!hadError && (query || sent.length) && error(Errors.connection('CONNECTION_CLOSED', options, socket));
|
|
1414
|
+
closedTime = performance$1.now();
|
|
1415
|
+
hadError && options.shared.retries++;
|
|
1416
|
+
delay = (typeof backoff === 'function' ? backoff(options.shared.retries) : backoff) * 1000;
|
|
1417
|
+
onclose(connection, Errors.connection('CONNECTION_CLOSED', options, socket));
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/* Handlers */
|
|
1421
|
+
function handle(xs, x = xs[0]) {
|
|
1422
|
+
(
|
|
1423
|
+
x === 68 ? DataRow : // D
|
|
1424
|
+
x === 100 ? CopyData : // d
|
|
1425
|
+
x === 65 ? NotificationResponse : // A
|
|
1426
|
+
x === 83 ? ParameterStatus : // S
|
|
1427
|
+
x === 90 ? ReadyForQuery : // Z
|
|
1428
|
+
x === 67 ? CommandComplete : // C
|
|
1429
|
+
x === 50 ? BindComplete : // 2
|
|
1430
|
+
x === 49 ? ParseComplete : // 1
|
|
1431
|
+
x === 116 ? ParameterDescription : // t
|
|
1432
|
+
x === 84 ? RowDescription : // T
|
|
1433
|
+
x === 82 ? Authentication : // R
|
|
1434
|
+
x === 110 ? NoData : // n
|
|
1435
|
+
x === 75 ? BackendKeyData : // K
|
|
1436
|
+
x === 69 ? ErrorResponse : // E
|
|
1437
|
+
x === 115 ? PortalSuspended : // s
|
|
1438
|
+
x === 51 ? CloseComplete : // 3
|
|
1439
|
+
x === 71 ? CopyInResponse : // G
|
|
1440
|
+
x === 78 ? NoticeResponse : // N
|
|
1441
|
+
x === 72 ? CopyOutResponse : // H
|
|
1442
|
+
x === 99 ? CopyDone : // c
|
|
1443
|
+
x === 73 ? EmptyQueryResponse : // I
|
|
1444
|
+
x === 86 ? FunctionCallResponse : // V
|
|
1445
|
+
x === 118 ? NegotiateProtocolVersion : // v
|
|
1446
|
+
x === 87 ? CopyBothResponse : // W
|
|
1447
|
+
/* c8 ignore next */
|
|
1448
|
+
UnknownMessage
|
|
1449
|
+
)(xs);
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
function DataRow(x) {
|
|
1453
|
+
let index = 7;
|
|
1454
|
+
let length;
|
|
1455
|
+
let column;
|
|
1456
|
+
let value;
|
|
1457
|
+
|
|
1458
|
+
const row = query.isRaw ? new Array(query.statement.columns.length) : {};
|
|
1459
|
+
for (let i = 0; i < query.statement.columns.length; i++) {
|
|
1460
|
+
column = query.statement.columns[i];
|
|
1461
|
+
length = x.readInt32BE(index);
|
|
1462
|
+
index += 4;
|
|
1463
|
+
|
|
1464
|
+
value = length === -1
|
|
1465
|
+
? null
|
|
1466
|
+
: query.isRaw === true
|
|
1467
|
+
? x.subarray(index, index += length)
|
|
1468
|
+
: column.parser === undefined
|
|
1469
|
+
? x.toString('utf8', index, index += length)
|
|
1470
|
+
: column.parser.array === true
|
|
1471
|
+
? column.parser(x.toString('utf8', index + 1, index += length))
|
|
1472
|
+
: column.parser(x.toString('utf8', index, index += length));
|
|
1473
|
+
|
|
1474
|
+
query.isRaw
|
|
1475
|
+
? (row[i] = query.isRaw === true
|
|
1476
|
+
? value
|
|
1477
|
+
: transform.value.from ? transform.value.from(value, column) : value)
|
|
1478
|
+
: (row[column.name] = transform.value.from ? transform.value.from(value, column) : value);
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
query.forEachFn
|
|
1482
|
+
? query.forEachFn(transform.row.from ? transform.row.from(row) : row, result)
|
|
1483
|
+
: (result[rows++] = transform.row.from ? transform.row.from(row) : row);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
function ParameterStatus(x) {
|
|
1487
|
+
const [k, v] = x.toString('utf8', 5, x.length - 1).split(b.N);
|
|
1488
|
+
backendParameters[k] = v;
|
|
1489
|
+
if (options.parameters[k] !== v) {
|
|
1490
|
+
options.parameters[k] = v;
|
|
1491
|
+
onparameter && onparameter(k, v);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
function ReadyForQuery(x) {
|
|
1496
|
+
if (query) {
|
|
1497
|
+
if (errorResponse) {
|
|
1498
|
+
query.retried
|
|
1499
|
+
? errored(query.retried)
|
|
1500
|
+
: query.prepared && retryRoutines.has(errorResponse.routine)
|
|
1501
|
+
? retry(query, errorResponse)
|
|
1502
|
+
: errored(errorResponse);
|
|
1503
|
+
} else {
|
|
1504
|
+
query.resolve(results || result);
|
|
1505
|
+
}
|
|
1506
|
+
} else if (errorResponse) {
|
|
1507
|
+
errored(errorResponse);
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
query = results = errorResponse = null;
|
|
1511
|
+
result = new Result();
|
|
1512
|
+
connectTimer.cancel();
|
|
1513
|
+
|
|
1514
|
+
if (initial) {
|
|
1515
|
+
if (target_session_attrs) {
|
|
1516
|
+
if (!backendParameters.in_hot_standby || !backendParameters.default_transaction_read_only)
|
|
1517
|
+
return fetchState()
|
|
1518
|
+
else if (tryNext(target_session_attrs, backendParameters))
|
|
1519
|
+
return terminate()
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
if (needsTypes) {
|
|
1523
|
+
initial.reserve && (initial = null);
|
|
1524
|
+
return fetchArrayTypes()
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
initial && !initial.reserve && execute(initial);
|
|
1528
|
+
options.shared.retries = retries = 0;
|
|
1529
|
+
initial = null;
|
|
1530
|
+
return
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
while (sent.length && (query = sent.shift()) && (query.active = true, query.cancelled))
|
|
1534
|
+
Connection(options).cancel(query.state, query.cancelled.resolve, query.cancelled.reject);
|
|
1535
|
+
|
|
1536
|
+
if (query)
|
|
1537
|
+
return // Consider opening if able and sent.length < 50
|
|
1538
|
+
|
|
1539
|
+
connection.reserved
|
|
1540
|
+
? !connection.reserved.release && x[5] === 73 // I
|
|
1541
|
+
? ending
|
|
1542
|
+
? terminate()
|
|
1543
|
+
: (connection.reserved = null, onopen(connection))
|
|
1544
|
+
: connection.reserved()
|
|
1545
|
+
: ending
|
|
1546
|
+
? terminate()
|
|
1547
|
+
: onopen(connection);
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
function CommandComplete(x) {
|
|
1551
|
+
rows = 0;
|
|
1552
|
+
|
|
1553
|
+
for (let i = x.length - 1; i > 0; i--) {
|
|
1554
|
+
if (x[i] === 32 && x[i + 1] < 58 && result.count === null)
|
|
1555
|
+
result.count = +x.toString('utf8', i + 1, x.length - 1);
|
|
1556
|
+
if (x[i - 1] >= 65) {
|
|
1557
|
+
result.command = x.toString('utf8', 5, i);
|
|
1558
|
+
result.state = backend;
|
|
1559
|
+
break
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
final && (final(), final = null);
|
|
1564
|
+
|
|
1565
|
+
if (result.command === 'BEGIN' && max !== 1 && !connection.reserved)
|
|
1566
|
+
return errored(Errors.generic('UNSAFE_TRANSACTION', 'Only use sql.begin, sql.reserved or max: 1'))
|
|
1567
|
+
|
|
1568
|
+
if (query.options.simple)
|
|
1569
|
+
return BindComplete()
|
|
1570
|
+
|
|
1571
|
+
if (query.cursorFn) {
|
|
1572
|
+
result.count && query.cursorFn(result);
|
|
1573
|
+
write(Sync);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
function ParseComplete() {
|
|
1578
|
+
query.parsing = false;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function BindComplete() {
|
|
1582
|
+
!result.statement && (result.statement = query.statement);
|
|
1583
|
+
result.columns = query.statement.columns;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
function ParameterDescription(x) {
|
|
1587
|
+
const length = x.readUInt16BE(5);
|
|
1588
|
+
|
|
1589
|
+
for (let i = 0; i < length; ++i)
|
|
1590
|
+
!query.statement.types[i] && (query.statement.types[i] = x.readUInt32BE(7 + i * 4));
|
|
1591
|
+
|
|
1592
|
+
query.prepare && (statements[query.signature] = query.statement);
|
|
1593
|
+
query.describeFirst && !query.onlyDescribe && (write(prepared(query)), query.describeFirst = false);
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
function RowDescription(x) {
|
|
1597
|
+
if (result.command) {
|
|
1598
|
+
results = results || [result];
|
|
1599
|
+
results.push(result = new Result());
|
|
1600
|
+
result.count = null;
|
|
1601
|
+
query.statement.columns = null;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
const length = x.readUInt16BE(5);
|
|
1605
|
+
let index = 7;
|
|
1606
|
+
let start;
|
|
1607
|
+
|
|
1608
|
+
query.statement.columns = Array(length);
|
|
1609
|
+
|
|
1610
|
+
for (let i = 0; i < length; ++i) {
|
|
1611
|
+
start = index;
|
|
1612
|
+
while (x[index++] !== 0);
|
|
1613
|
+
const table = x.readUInt32BE(index);
|
|
1614
|
+
const number = x.readUInt16BE(index + 4);
|
|
1615
|
+
const type = x.readUInt32BE(index + 6);
|
|
1616
|
+
query.statement.columns[i] = {
|
|
1617
|
+
name: transform.column.from
|
|
1618
|
+
? transform.column.from(x.toString('utf8', start, index - 1))
|
|
1619
|
+
: x.toString('utf8', start, index - 1),
|
|
1620
|
+
parser: parsers[type],
|
|
1621
|
+
table,
|
|
1622
|
+
number,
|
|
1623
|
+
type
|
|
1624
|
+
};
|
|
1625
|
+
index += 18;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
result.statement = query.statement;
|
|
1629
|
+
if (query.onlyDescribe)
|
|
1630
|
+
return (query.resolve(query.statement), write(Sync))
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
async function Authentication(x, type = x.readUInt32BE(5)) {
|
|
1634
|
+
(
|
|
1635
|
+
type === 3 ? AuthenticationCleartextPassword :
|
|
1636
|
+
type === 5 ? AuthenticationMD5Password :
|
|
1637
|
+
type === 10 ? SASL :
|
|
1638
|
+
type === 11 ? SASLContinue :
|
|
1639
|
+
type === 12 ? SASLFinal :
|
|
1640
|
+
type !== 0 ? UnknownAuth :
|
|
1641
|
+
noop$2
|
|
1642
|
+
)(x, type);
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
/* c8 ignore next 5 */
|
|
1646
|
+
async function AuthenticationCleartextPassword() {
|
|
1647
|
+
const payload = await Pass();
|
|
1648
|
+
write(
|
|
1649
|
+
b().p().str(payload).z(1).end()
|
|
1650
|
+
);
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
async function AuthenticationMD5Password(x) {
|
|
1654
|
+
const payload = 'md5' + (
|
|
1655
|
+
await md5(
|
|
1656
|
+
Buffer.concat([
|
|
1657
|
+
Buffer.from(await md5((await Pass()) + user)),
|
|
1658
|
+
x.subarray(9)
|
|
1659
|
+
])
|
|
1660
|
+
)
|
|
1661
|
+
);
|
|
1662
|
+
write(
|
|
1663
|
+
b().p().str(payload).z(1).end()
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
async function SASL() {
|
|
1668
|
+
nonce = (await crypto.randomBytes(18)).toString('base64');
|
|
1669
|
+
b().p().str('SCRAM-SHA-256' + b.N);
|
|
1670
|
+
const i = b.i;
|
|
1671
|
+
write(b.inc(4).str('n,,n=*,r=' + nonce).i32(b.i - i - 4, i).end());
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
async function SASLContinue(x) {
|
|
1675
|
+
const res = x.toString('utf8', 9).split(',').reduce((acc, x) => (acc[x[0]] = x.slice(2), acc), {});
|
|
1676
|
+
|
|
1677
|
+
const saltedPassword = await crypto.pbkdf2Sync(
|
|
1678
|
+
await Pass(),
|
|
1679
|
+
Buffer.from(res.s, 'base64'),
|
|
1680
|
+
parseInt(res.i), 32,
|
|
1681
|
+
'sha256'
|
|
1682
|
+
);
|
|
1683
|
+
|
|
1684
|
+
const clientKey = await hmac(saltedPassword, 'Client Key');
|
|
1685
|
+
|
|
1686
|
+
const auth = 'n=*,r=' + nonce + ','
|
|
1687
|
+
+ 'r=' + res.r + ',s=' + res.s + ',i=' + res.i
|
|
1688
|
+
+ ',c=biws,r=' + res.r;
|
|
1689
|
+
|
|
1690
|
+
serverSignature = (await hmac(await hmac(saltedPassword, 'Server Key'), auth)).toString('base64');
|
|
1691
|
+
|
|
1692
|
+
const payload = 'c=biws,r=' + res.r + ',p=' + xor(
|
|
1693
|
+
clientKey, Buffer.from(await hmac(await sha256(clientKey), auth))
|
|
1694
|
+
).toString('base64');
|
|
1695
|
+
|
|
1696
|
+
write(
|
|
1697
|
+
b().p().str(payload).end()
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
function SASLFinal(x) {
|
|
1702
|
+
if (x.toString('utf8', 9).split(b.N, 1)[0].slice(2) === serverSignature)
|
|
1703
|
+
return
|
|
1704
|
+
/* c8 ignore next 5 */
|
|
1705
|
+
errored(Errors.generic('SASL_SIGNATURE_MISMATCH', 'The server did not return the correct signature'));
|
|
1706
|
+
socket.destroy();
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
function Pass() {
|
|
1710
|
+
return Promise.resolve(typeof options.pass === 'function'
|
|
1711
|
+
? options.pass()
|
|
1712
|
+
: options.pass
|
|
1713
|
+
)
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
function NoData() {
|
|
1717
|
+
result.statement = query.statement;
|
|
1718
|
+
result.statement.columns = [];
|
|
1719
|
+
if (query.onlyDescribe)
|
|
1720
|
+
return (query.resolve(query.statement), write(Sync))
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
function BackendKeyData(x) {
|
|
1724
|
+
backend.pid = x.readUInt32BE(5);
|
|
1725
|
+
backend.secret = x.readUInt32BE(9);
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
async function fetchArrayTypes() {
|
|
1729
|
+
needsTypes = false;
|
|
1730
|
+
const types = await new Query([`
|
|
1731
|
+
select b.oid, b.typarray
|
|
1732
|
+
from pg_catalog.pg_type a
|
|
1733
|
+
left join pg_catalog.pg_type b on b.oid = a.typelem
|
|
1734
|
+
where a.typcategory = 'A'
|
|
1735
|
+
group by b.oid, b.typarray
|
|
1736
|
+
order by b.oid
|
|
1737
|
+
`], [], execute);
|
|
1738
|
+
types.forEach(({ oid, typarray }) => addArrayType(oid, typarray));
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
function addArrayType(oid, typarray) {
|
|
1742
|
+
if (!!options.parsers[typarray] && !!options.serializers[typarray]) return
|
|
1743
|
+
const parser = options.parsers[oid];
|
|
1744
|
+
options.shared.typeArrayMap[oid] = typarray;
|
|
1745
|
+
options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray);
|
|
1746
|
+
options.parsers[typarray].array = true;
|
|
1747
|
+
options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options, typarray);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
function tryNext(x, xs) {
|
|
1751
|
+
return (
|
|
1752
|
+
(x === 'read-write' && xs.default_transaction_read_only === 'on') ||
|
|
1753
|
+
(x === 'read-only' && xs.default_transaction_read_only === 'off') ||
|
|
1754
|
+
(x === 'primary' && xs.in_hot_standby === 'on') ||
|
|
1755
|
+
(x === 'standby' && xs.in_hot_standby === 'off') ||
|
|
1756
|
+
(x === 'prefer-standby' && xs.in_hot_standby === 'off' && options.host[retries])
|
|
1757
|
+
)
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
function fetchState() {
|
|
1761
|
+
const query = new Query([`
|
|
1762
|
+
show transaction_read_only;
|
|
1763
|
+
select pg_catalog.pg_is_in_recovery()
|
|
1764
|
+
`], [], execute, null, { simple: true });
|
|
1765
|
+
query.resolve = ([[a], [b]]) => {
|
|
1766
|
+
backendParameters.default_transaction_read_only = a.transaction_read_only;
|
|
1767
|
+
backendParameters.in_hot_standby = b.pg_is_in_recovery ? 'on' : 'off';
|
|
1768
|
+
};
|
|
1769
|
+
query.execute();
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
function ErrorResponse(x) {
|
|
1773
|
+
if (query) {
|
|
1774
|
+
(query.cursorFn || query.describeFirst) && write(Sync);
|
|
1775
|
+
errorResponse = Errors.postgres(parseError(x));
|
|
1776
|
+
} else {
|
|
1777
|
+
errored(Errors.postgres(parseError(x)));
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
function retry(q, error) {
|
|
1782
|
+
delete statements[q.signature];
|
|
1783
|
+
q.retried = error;
|
|
1784
|
+
execute(q);
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
function NotificationResponse(x) {
|
|
1788
|
+
if (!onnotify)
|
|
1789
|
+
return
|
|
1790
|
+
|
|
1791
|
+
let index = 9;
|
|
1792
|
+
while (x[index++] !== 0);
|
|
1793
|
+
onnotify(
|
|
1794
|
+
x.toString('utf8', 9, index - 1),
|
|
1795
|
+
x.toString('utf8', index, x.length - 1)
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
async function PortalSuspended() {
|
|
1800
|
+
try {
|
|
1801
|
+
const x = await Promise.resolve(query.cursorFn(result));
|
|
1802
|
+
rows = 0;
|
|
1803
|
+
x === CLOSE
|
|
1804
|
+
? write(Close(query.portal))
|
|
1805
|
+
: (result = new Result(), write(Execute('', query.cursorRows)));
|
|
1806
|
+
} catch (err) {
|
|
1807
|
+
write(Sync);
|
|
1808
|
+
query.reject(err);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
function CloseComplete() {
|
|
1813
|
+
result.count && query.cursorFn(result);
|
|
1814
|
+
query.resolve(result);
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
function CopyInResponse() {
|
|
1818
|
+
stream = new Stream.Writable({
|
|
1819
|
+
autoDestroy: true,
|
|
1820
|
+
write(chunk, encoding, callback) {
|
|
1821
|
+
socket.write(b().d().raw(chunk).end(), callback);
|
|
1822
|
+
},
|
|
1823
|
+
destroy(error, callback) {
|
|
1824
|
+
callback(error);
|
|
1825
|
+
socket.write(b().f().str(error + b.N).end());
|
|
1826
|
+
stream = null;
|
|
1827
|
+
},
|
|
1828
|
+
final(callback) {
|
|
1829
|
+
socket.write(b().c().end());
|
|
1830
|
+
final = callback;
|
|
1831
|
+
stream = null;
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
query.resolve(stream);
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
function CopyOutResponse() {
|
|
1838
|
+
stream = new Stream.Readable({
|
|
1839
|
+
read() { socket.resume(); }
|
|
1840
|
+
});
|
|
1841
|
+
query.resolve(stream);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
/* c8 ignore next 3 */
|
|
1845
|
+
function CopyBothResponse() {
|
|
1846
|
+
stream = new Stream.Duplex({
|
|
1847
|
+
autoDestroy: true,
|
|
1848
|
+
read() { socket.resume(); },
|
|
1849
|
+
/* c8 ignore next 11 */
|
|
1850
|
+
write(chunk, encoding, callback) {
|
|
1851
|
+
socket.write(b().d().raw(chunk).end(), callback);
|
|
1852
|
+
},
|
|
1853
|
+
destroy(error, callback) {
|
|
1854
|
+
callback(error);
|
|
1855
|
+
socket.write(b().f().str(error + b.N).end());
|
|
1856
|
+
stream = null;
|
|
1857
|
+
},
|
|
1858
|
+
final(callback) {
|
|
1859
|
+
socket.write(b().c().end());
|
|
1860
|
+
final = callback;
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
query.resolve(stream);
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
function CopyData(x) {
|
|
1867
|
+
stream && (stream.push(x.subarray(5)) || socket.pause());
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
function CopyDone() {
|
|
1871
|
+
stream && stream.push(null);
|
|
1872
|
+
stream = null;
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
function NoticeResponse(x) {
|
|
1876
|
+
onnotice
|
|
1877
|
+
? onnotice(parseError(x))
|
|
1878
|
+
: console.log(parseError(x)); // eslint-disable-line
|
|
1879
|
+
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
/* c8 ignore next 3 */
|
|
1883
|
+
function EmptyQueryResponse() {
|
|
1884
|
+
/* noop */
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
/* c8 ignore next 3 */
|
|
1888
|
+
function FunctionCallResponse() {
|
|
1889
|
+
errored(Errors.notSupported('FunctionCallResponse'));
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
/* c8 ignore next 3 */
|
|
1893
|
+
function NegotiateProtocolVersion() {
|
|
1894
|
+
errored(Errors.notSupported('NegotiateProtocolVersion'));
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
/* c8 ignore next 3 */
|
|
1898
|
+
function UnknownMessage(x) {
|
|
1899
|
+
console.error('Postgres.js : Unknown Message:', x[0]); // eslint-disable-line
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
/* c8 ignore next 3 */
|
|
1903
|
+
function UnknownAuth(x, type) {
|
|
1904
|
+
console.error('Postgres.js : Unknown Auth:', type); // eslint-disable-line
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
/* Messages */
|
|
1908
|
+
function Bind(parameters, types, statement = '', portal = '') {
|
|
1909
|
+
let prev
|
|
1910
|
+
, type;
|
|
1911
|
+
|
|
1912
|
+
b().B().str(portal + b.N).str(statement + b.N).i16(0).i16(parameters.length);
|
|
1913
|
+
|
|
1914
|
+
parameters.forEach((x, i) => {
|
|
1915
|
+
if (x === null)
|
|
1916
|
+
return b.i32(0xFFFFFFFF)
|
|
1917
|
+
|
|
1918
|
+
type = types[i];
|
|
1919
|
+
parameters[i] = x = type in options.serializers
|
|
1920
|
+
? options.serializers[type](x)
|
|
1921
|
+
: '' + x;
|
|
1922
|
+
|
|
1923
|
+
prev = b.i;
|
|
1924
|
+
b.inc(4).str(x).i32(b.i - prev - 4, prev);
|
|
1925
|
+
});
|
|
1926
|
+
|
|
1927
|
+
b.i16(0);
|
|
1928
|
+
|
|
1929
|
+
return b.end()
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
function Parse(str, parameters, types, name = '') {
|
|
1933
|
+
b().P().str(name + b.N).str(str + b.N).i16(parameters.length);
|
|
1934
|
+
parameters.forEach((x, i) => b.i32(types[i] || 0));
|
|
1935
|
+
return b.end()
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
function Describe(x, name = '') {
|
|
1939
|
+
return b().D().str(x).str(name + b.N).end()
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
function Execute(portal = '', rows = 0) {
|
|
1943
|
+
return Buffer.concat([
|
|
1944
|
+
b().E().str(portal + b.N).i32(rows).end(),
|
|
1945
|
+
Flush
|
|
1946
|
+
])
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
function Close(portal = '') {
|
|
1950
|
+
return Buffer.concat([
|
|
1951
|
+
b().C().str('P').str(portal + b.N).end(),
|
|
1952
|
+
b().S().end()
|
|
1953
|
+
])
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
function StartupMessage() {
|
|
1957
|
+
return cancelMessage || b().inc(4).i16(3).z(2).str(
|
|
1958
|
+
Object.entries(Object.assign({
|
|
1959
|
+
user,
|
|
1960
|
+
database,
|
|
1961
|
+
client_encoding: 'UTF8'
|
|
1962
|
+
},
|
|
1963
|
+
options.connection
|
|
1964
|
+
)).filter(([, v]) => v).map(([k, v]) => k + b.N + v).join(b.N)
|
|
1965
|
+
).z(2).end(0)
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
function parseError(x) {
|
|
1971
|
+
const error = {};
|
|
1972
|
+
let start = 5;
|
|
1973
|
+
for (let i = 5; i < x.length - 1; i++) {
|
|
1974
|
+
if (x[i] === 0) {
|
|
1975
|
+
error[errorFields[x[start]]] = x.toString('utf8', start + 1, i);
|
|
1976
|
+
start = i + 1;
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
return error
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
function md5(x) {
|
|
1983
|
+
return crypto.createHash('md5').update(x).digest('hex')
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
function hmac(key, x) {
|
|
1987
|
+
return crypto.createHmac('sha256', key).update(x).digest()
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
function sha256(x) {
|
|
1991
|
+
return crypto.createHash('sha256').update(x).digest()
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
function xor(a, b) {
|
|
1995
|
+
const length = Math.max(a.length, b.length);
|
|
1996
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
1997
|
+
for (let i = 0; i < length; i++)
|
|
1998
|
+
buffer[i] = a[i] ^ b[i];
|
|
1999
|
+
return buffer
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
function timer(fn, seconds) {
|
|
2003
|
+
seconds = typeof seconds === 'function' ? seconds() : seconds;
|
|
2004
|
+
if (!seconds)
|
|
2005
|
+
return { cancel: noop$2, start: noop$2 }
|
|
2006
|
+
|
|
2007
|
+
let timer;
|
|
2008
|
+
return {
|
|
2009
|
+
cancel() {
|
|
2010
|
+
timer && (clearTimeout(timer), timer = null);
|
|
2011
|
+
},
|
|
2012
|
+
start() {
|
|
2013
|
+
timer && clearTimeout(timer);
|
|
2014
|
+
timer = setTimeout(done, seconds * 1000, arguments);
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
function done(args) {
|
|
2019
|
+
fn.apply(null, args);
|
|
2020
|
+
timer = null;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
const noop$1 = () => { /* noop */ };
|
|
2025
|
+
|
|
2026
|
+
function Subscribe(postgres, options) {
|
|
2027
|
+
const subscribers = new Map()
|
|
2028
|
+
, slot = 'postgresjs_' + Math.random().toString(36).slice(2)
|
|
2029
|
+
, state = {};
|
|
2030
|
+
|
|
2031
|
+
let connection
|
|
2032
|
+
, stream
|
|
2033
|
+
, ended = false;
|
|
2034
|
+
|
|
2035
|
+
const sql = subscribe.sql = postgres({
|
|
2036
|
+
...options,
|
|
2037
|
+
transform: { column: {}, value: {}, row: {} },
|
|
2038
|
+
max: 1,
|
|
2039
|
+
fetch_types: false,
|
|
2040
|
+
idle_timeout: null,
|
|
2041
|
+
max_lifetime: null,
|
|
2042
|
+
connection: {
|
|
2043
|
+
...options.connection,
|
|
2044
|
+
replication: 'database'
|
|
2045
|
+
},
|
|
2046
|
+
onclose: async function() {
|
|
2047
|
+
if (ended)
|
|
2048
|
+
return
|
|
2049
|
+
stream = null;
|
|
2050
|
+
state.pid = state.secret = undefined;
|
|
2051
|
+
connected(await init(sql, slot, options.publications));
|
|
2052
|
+
subscribers.forEach(event => event.forEach(({ onsubscribe }) => onsubscribe()));
|
|
2053
|
+
},
|
|
2054
|
+
no_subscribe: true
|
|
2055
|
+
});
|
|
2056
|
+
|
|
2057
|
+
const end = sql.end
|
|
2058
|
+
, close = sql.close;
|
|
2059
|
+
|
|
2060
|
+
sql.end = async() => {
|
|
2061
|
+
ended = true;
|
|
2062
|
+
stream && (await new Promise(r => (stream.once('close', r), stream.end())));
|
|
2063
|
+
return end()
|
|
2064
|
+
};
|
|
2065
|
+
|
|
2066
|
+
sql.close = async() => {
|
|
2067
|
+
stream && (await new Promise(r => (stream.once('close', r), stream.end())));
|
|
2068
|
+
return close()
|
|
2069
|
+
};
|
|
2070
|
+
|
|
2071
|
+
return subscribe
|
|
2072
|
+
|
|
2073
|
+
async function subscribe(event, fn, onsubscribe = noop$1, onerror = noop$1) {
|
|
2074
|
+
event = parseEvent(event);
|
|
2075
|
+
|
|
2076
|
+
if (!connection)
|
|
2077
|
+
connection = init(sql, slot, options.publications);
|
|
2078
|
+
|
|
2079
|
+
const subscriber = { fn, onsubscribe };
|
|
2080
|
+
const fns = subscribers.has(event)
|
|
2081
|
+
? subscribers.get(event).add(subscriber)
|
|
2082
|
+
: subscribers.set(event, new Set([subscriber])).get(event);
|
|
2083
|
+
|
|
2084
|
+
const unsubscribe = () => {
|
|
2085
|
+
fns.delete(subscriber);
|
|
2086
|
+
fns.size === 0 && subscribers.delete(event);
|
|
2087
|
+
};
|
|
2088
|
+
|
|
2089
|
+
return connection.then(x => {
|
|
2090
|
+
connected(x);
|
|
2091
|
+
onsubscribe();
|
|
2092
|
+
stream && stream.on('error', onerror);
|
|
2093
|
+
return { unsubscribe, state, sql }
|
|
2094
|
+
})
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
function connected(x) {
|
|
2098
|
+
stream = x.stream;
|
|
2099
|
+
state.pid = x.state.pid;
|
|
2100
|
+
state.secret = x.state.secret;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
async function init(sql, slot, publications) {
|
|
2104
|
+
if (!publications)
|
|
2105
|
+
throw new Error('Missing publication names')
|
|
2106
|
+
|
|
2107
|
+
const xs = await sql.unsafe(
|
|
2108
|
+
`CREATE_REPLICATION_SLOT ${ slot } TEMPORARY LOGICAL pgoutput NOEXPORT_SNAPSHOT`
|
|
2109
|
+
);
|
|
2110
|
+
|
|
2111
|
+
const [x] = xs;
|
|
2112
|
+
|
|
2113
|
+
const stream = await sql.unsafe(
|
|
2114
|
+
`START_REPLICATION SLOT ${ slot } LOGICAL ${
|
|
2115
|
+
x.consistent_point
|
|
2116
|
+
} (proto_version '1', publication_names '${ publications }')`
|
|
2117
|
+
).writable();
|
|
2118
|
+
|
|
2119
|
+
const state = {
|
|
2120
|
+
lsn: Buffer.concat(x.consistent_point.split('/').map(x => Buffer.from(('00000000' + x).slice(-8), 'hex')))
|
|
2121
|
+
};
|
|
2122
|
+
|
|
2123
|
+
stream.on('data', data);
|
|
2124
|
+
stream.on('error', error);
|
|
2125
|
+
stream.on('close', sql.close);
|
|
2126
|
+
|
|
2127
|
+
return { stream, state: xs.state }
|
|
2128
|
+
|
|
2129
|
+
function error(e) {
|
|
2130
|
+
console.error('Unexpected error during logical streaming - reconnecting', e); // eslint-disable-line
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
function data(x) {
|
|
2134
|
+
if (x[0] === 0x77) {
|
|
2135
|
+
parse(x.subarray(25), state, sql.options.parsers, handle, options.transform);
|
|
2136
|
+
} else if (x[0] === 0x6b && x[17]) {
|
|
2137
|
+
state.lsn = x.subarray(1, 9);
|
|
2138
|
+
pong();
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
function handle(a, b) {
|
|
2143
|
+
const path = b.relation.schema + '.' + b.relation.table;
|
|
2144
|
+
call('*', a, b);
|
|
2145
|
+
call('*:' + path, a, b);
|
|
2146
|
+
b.relation.keys.length && call('*:' + path + '=' + b.relation.keys.map(x => a[x.name]), a, b);
|
|
2147
|
+
call(b.command, a, b);
|
|
2148
|
+
call(b.command + ':' + path, a, b);
|
|
2149
|
+
b.relation.keys.length && call(b.command + ':' + path + '=' + b.relation.keys.map(x => a[x.name]), a, b);
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
function pong() {
|
|
2153
|
+
const x = Buffer.alloc(34);
|
|
2154
|
+
x[0] = 'r'.charCodeAt(0);
|
|
2155
|
+
x.fill(state.lsn, 1);
|
|
2156
|
+
x.writeBigInt64BE(BigInt(Date.now() - Date.UTC(2000, 0, 1)) * BigInt(1000), 25);
|
|
2157
|
+
stream.write(x);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
function call(x, a, b) {
|
|
2162
|
+
subscribers.has(x) && subscribers.get(x).forEach(({ fn }) => fn(a, b, x));
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
function Time(x) {
|
|
2167
|
+
return new Date(Date.UTC(2000, 0, 1) + Number(x / BigInt(1000)))
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
function parse(x, state, parsers, handle, transform) {
|
|
2171
|
+
const char = (acc, [k, v]) => (acc[k.charCodeAt(0)] = v, acc);
|
|
2172
|
+
|
|
2173
|
+
Object.entries({
|
|
2174
|
+
R: x => { // Relation
|
|
2175
|
+
let i = 1;
|
|
2176
|
+
const r = state[x.readUInt32BE(i)] = {
|
|
2177
|
+
schema: x.toString('utf8', i += 4, i = x.indexOf(0, i)) || 'pg_catalog',
|
|
2178
|
+
table: x.toString('utf8', i + 1, i = x.indexOf(0, i + 1)),
|
|
2179
|
+
columns: Array(x.readUInt16BE(i += 2)),
|
|
2180
|
+
keys: []
|
|
2181
|
+
};
|
|
2182
|
+
i += 2;
|
|
2183
|
+
|
|
2184
|
+
let columnIndex = 0
|
|
2185
|
+
, column;
|
|
2186
|
+
|
|
2187
|
+
while (i < x.length) {
|
|
2188
|
+
column = r.columns[columnIndex++] = {
|
|
2189
|
+
key: x[i++],
|
|
2190
|
+
name: transform.column.from
|
|
2191
|
+
? transform.column.from(x.toString('utf8', i, i = x.indexOf(0, i)))
|
|
2192
|
+
: x.toString('utf8', i, i = x.indexOf(0, i)),
|
|
2193
|
+
type: x.readUInt32BE(i += 1),
|
|
2194
|
+
parser: parsers[x.readUInt32BE(i)],
|
|
2195
|
+
atttypmod: x.readUInt32BE(i += 4)
|
|
2196
|
+
};
|
|
2197
|
+
|
|
2198
|
+
column.key && r.keys.push(column);
|
|
2199
|
+
i += 4;
|
|
2200
|
+
}
|
|
2201
|
+
},
|
|
2202
|
+
Y: () => { /* noop */ }, // Type
|
|
2203
|
+
O: () => { /* noop */ }, // Origin
|
|
2204
|
+
B: x => { // Begin
|
|
2205
|
+
state.date = Time(x.readBigInt64BE(9));
|
|
2206
|
+
state.lsn = x.subarray(1, 9);
|
|
2207
|
+
},
|
|
2208
|
+
I: x => { // Insert
|
|
2209
|
+
let i = 1;
|
|
2210
|
+
const relation = state[x.readUInt32BE(i)];
|
|
2211
|
+
const { row } = tuples(x, relation.columns, i += 7, transform);
|
|
2212
|
+
|
|
2213
|
+
handle(row, {
|
|
2214
|
+
command: 'insert',
|
|
2215
|
+
relation
|
|
2216
|
+
});
|
|
2217
|
+
},
|
|
2218
|
+
D: x => { // Delete
|
|
2219
|
+
let i = 1;
|
|
2220
|
+
const relation = state[x.readUInt32BE(i)];
|
|
2221
|
+
i += 4;
|
|
2222
|
+
const key = x[i] === 75;
|
|
2223
|
+
handle(key || x[i] === 79
|
|
2224
|
+
? tuples(x, relation.columns, i += 3, transform).row
|
|
2225
|
+
: null
|
|
2226
|
+
, {
|
|
2227
|
+
command: 'delete',
|
|
2228
|
+
relation,
|
|
2229
|
+
key
|
|
2230
|
+
});
|
|
2231
|
+
},
|
|
2232
|
+
U: x => { // Update
|
|
2233
|
+
let i = 1;
|
|
2234
|
+
const relation = state[x.readUInt32BE(i)];
|
|
2235
|
+
i += 4;
|
|
2236
|
+
const key = x[i] === 75;
|
|
2237
|
+
const xs = key || x[i] === 79
|
|
2238
|
+
? tuples(x, relation.columns, i += 3, transform)
|
|
2239
|
+
: null;
|
|
2240
|
+
|
|
2241
|
+
xs && (i = xs.i);
|
|
2242
|
+
|
|
2243
|
+
const { row } = tuples(x, relation.columns, i + 3, transform);
|
|
2244
|
+
|
|
2245
|
+
handle(row, {
|
|
2246
|
+
command: 'update',
|
|
2247
|
+
relation,
|
|
2248
|
+
key,
|
|
2249
|
+
old: xs && xs.row
|
|
2250
|
+
});
|
|
2251
|
+
},
|
|
2252
|
+
T: () => { /* noop */ }, // Truncate,
|
|
2253
|
+
C: () => { /* noop */ } // Commit
|
|
2254
|
+
}).reduce(char, {})[x[0]](x);
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
function tuples(x, columns, xi, transform) {
|
|
2258
|
+
let type
|
|
2259
|
+
, column
|
|
2260
|
+
, value;
|
|
2261
|
+
|
|
2262
|
+
const row = transform.raw ? new Array(columns.length) : {};
|
|
2263
|
+
for (let i = 0; i < columns.length; i++) {
|
|
2264
|
+
type = x[xi++];
|
|
2265
|
+
column = columns[i];
|
|
2266
|
+
value = type === 110 // n
|
|
2267
|
+
? null
|
|
2268
|
+
: type === 117 // u
|
|
2269
|
+
? undefined
|
|
2270
|
+
: column.parser === undefined
|
|
2271
|
+
? x.toString('utf8', xi + 4, xi += 4 + x.readUInt32BE(xi))
|
|
2272
|
+
: column.parser.array === true
|
|
2273
|
+
? column.parser(x.toString('utf8', xi + 5, xi += 4 + x.readUInt32BE(xi)))
|
|
2274
|
+
: column.parser(x.toString('utf8', xi + 4, xi += 4 + x.readUInt32BE(xi)));
|
|
2275
|
+
|
|
2276
|
+
transform.raw
|
|
2277
|
+
? (row[i] = transform.raw === true
|
|
2278
|
+
? value
|
|
2279
|
+
: transform.value.from ? transform.value.from(value, column) : value)
|
|
2280
|
+
: (row[column.name] = transform.value.from
|
|
2281
|
+
? transform.value.from(value, column)
|
|
2282
|
+
: value
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
return { i: xi, row: transform.row.from ? transform.row.from(row) : row }
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
function parseEvent(x) {
|
|
2290
|
+
const xs = x.match(/^(\*|insert|update|delete)?:?([^.]+?\.?[^=]+)?=?(.+)?/i) || [];
|
|
2291
|
+
|
|
2292
|
+
if (!xs)
|
|
2293
|
+
throw new Error('Malformed subscribe pattern: ' + x)
|
|
2294
|
+
|
|
2295
|
+
const [, command, path, key] = xs;
|
|
2296
|
+
|
|
2297
|
+
return (command || '*')
|
|
2298
|
+
+ (path ? ':' + (path.indexOf('.') === -1 ? 'public.' + path : path) : '')
|
|
2299
|
+
+ (key ? '=' + key : '')
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
function largeObject(sql, oid, mode = 0x00020000 | 0x00040000) {
|
|
2303
|
+
return new Promise(async(resolve, reject) => {
|
|
2304
|
+
await sql.begin(async sql => {
|
|
2305
|
+
let finish;
|
|
2306
|
+
!oid && ([{ oid }] = await sql`select lo_creat(-1) as oid`);
|
|
2307
|
+
const [{ fd }] = await sql`select lo_open(${ oid }, ${ mode }) as fd`;
|
|
2308
|
+
|
|
2309
|
+
const lo = {
|
|
2310
|
+
writable,
|
|
2311
|
+
readable,
|
|
2312
|
+
close : () => sql`select lo_close(${ fd })`.then(finish),
|
|
2313
|
+
tell : () => sql`select lo_tell64(${ fd })`,
|
|
2314
|
+
read : (x) => sql`select loread(${ fd }, ${ x }) as data`,
|
|
2315
|
+
write : (x) => sql`select lowrite(${ fd }, ${ x })`,
|
|
2316
|
+
truncate : (x) => sql`select lo_truncate64(${ fd }, ${ x })`,
|
|
2317
|
+
seek : (x, whence = 0) => sql`select lo_lseek64(${ fd }, ${ x }, ${ whence })`,
|
|
2318
|
+
size : () => sql`
|
|
2319
|
+
select
|
|
2320
|
+
lo_lseek64(${ fd }, location, 0) as position,
|
|
2321
|
+
seek.size
|
|
2322
|
+
from (
|
|
2323
|
+
select
|
|
2324
|
+
lo_lseek64($1, 0, 2) as size,
|
|
2325
|
+
tell.location
|
|
2326
|
+
from (select lo_tell64($1) as location) tell
|
|
2327
|
+
) seek
|
|
2328
|
+
`
|
|
2329
|
+
};
|
|
2330
|
+
|
|
2331
|
+
resolve(lo);
|
|
2332
|
+
|
|
2333
|
+
return new Promise(async r => finish = r)
|
|
2334
|
+
|
|
2335
|
+
async function readable({
|
|
2336
|
+
highWaterMark = 2048 * 8,
|
|
2337
|
+
start = 0,
|
|
2338
|
+
end = Infinity
|
|
2339
|
+
} = {}) {
|
|
2340
|
+
let max = end - start;
|
|
2341
|
+
start && await lo.seek(start);
|
|
2342
|
+
return new Stream.Readable({
|
|
2343
|
+
highWaterMark,
|
|
2344
|
+
async read(size) {
|
|
2345
|
+
const l = size > max ? size - max : size;
|
|
2346
|
+
max -= size;
|
|
2347
|
+
const [{ data }] = await lo.read(l);
|
|
2348
|
+
this.push(data);
|
|
2349
|
+
if (data.length < size)
|
|
2350
|
+
this.push(null);
|
|
2351
|
+
}
|
|
2352
|
+
})
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
async function writable({
|
|
2356
|
+
highWaterMark = 2048 * 8,
|
|
2357
|
+
start = 0
|
|
2358
|
+
} = {}) {
|
|
2359
|
+
start && await lo.seek(start);
|
|
2360
|
+
return new Stream.Writable({
|
|
2361
|
+
highWaterMark,
|
|
2362
|
+
write(chunk, encoding, callback) {
|
|
2363
|
+
lo.write(chunk).then(() => callback(), callback);
|
|
2364
|
+
}
|
|
2365
|
+
})
|
|
2366
|
+
}
|
|
2367
|
+
}).catch(reject);
|
|
2368
|
+
})
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
Object.assign(Postgres, {
|
|
2372
|
+
PostgresError,
|
|
2373
|
+
toPascal,
|
|
2374
|
+
pascal,
|
|
2375
|
+
toCamel,
|
|
2376
|
+
camel,
|
|
2377
|
+
toKebab,
|
|
2378
|
+
kebab,
|
|
2379
|
+
fromPascal,
|
|
2380
|
+
fromCamel,
|
|
2381
|
+
fromKebab,
|
|
2382
|
+
BigInt: {
|
|
2383
|
+
to: 20,
|
|
2384
|
+
from: [20],
|
|
2385
|
+
parse: x => BigInt(x), // eslint-disable-line
|
|
2386
|
+
serialize: x => x.toString()
|
|
2387
|
+
}
|
|
2388
|
+
});
|
|
2389
|
+
|
|
2390
|
+
function Postgres(a, b) {
|
|
2391
|
+
const options = parseOptions(a, b)
|
|
2392
|
+
, subscribe = options.no_subscribe || Subscribe(Postgres, { ...options });
|
|
2393
|
+
|
|
2394
|
+
let ending = false;
|
|
2395
|
+
|
|
2396
|
+
const queries = Queue()
|
|
2397
|
+
, connecting = Queue()
|
|
2398
|
+
, reserved = Queue()
|
|
2399
|
+
, closed = Queue()
|
|
2400
|
+
, ended = Queue()
|
|
2401
|
+
, open = Queue()
|
|
2402
|
+
, busy = Queue()
|
|
2403
|
+
, full = Queue()
|
|
2404
|
+
, queues = { connecting, closed};
|
|
2405
|
+
|
|
2406
|
+
const connections = [...Array(options.max)].map(() => Connection(options, queues, { onopen, onend, onclose }));
|
|
2407
|
+
|
|
2408
|
+
const sql = Sql(handler);
|
|
2409
|
+
|
|
2410
|
+
Object.assign(sql, {
|
|
2411
|
+
get parameters() { return options.parameters },
|
|
2412
|
+
largeObject: largeObject.bind(null, sql),
|
|
2413
|
+
subscribe,
|
|
2414
|
+
CLOSE,
|
|
2415
|
+
END: CLOSE,
|
|
2416
|
+
PostgresError,
|
|
2417
|
+
options,
|
|
2418
|
+
reserve,
|
|
2419
|
+
listen,
|
|
2420
|
+
begin,
|
|
2421
|
+
close,
|
|
2422
|
+
end
|
|
2423
|
+
});
|
|
2424
|
+
|
|
2425
|
+
return sql
|
|
2426
|
+
|
|
2427
|
+
function Sql(handler) {
|
|
2428
|
+
handler.debug = options.debug;
|
|
2429
|
+
|
|
2430
|
+
Object.entries(options.types).reduce((acc, [name, type]) => {
|
|
2431
|
+
acc[name] = (x) => new Parameter(x, type.to);
|
|
2432
|
+
return acc
|
|
2433
|
+
}, typed);
|
|
2434
|
+
|
|
2435
|
+
Object.assign(sql, {
|
|
2436
|
+
types: typed,
|
|
2437
|
+
typed,
|
|
2438
|
+
unsafe,
|
|
2439
|
+
notify,
|
|
2440
|
+
array,
|
|
2441
|
+
json,
|
|
2442
|
+
file
|
|
2443
|
+
});
|
|
2444
|
+
|
|
2445
|
+
return sql
|
|
2446
|
+
|
|
2447
|
+
function typed(value, type) {
|
|
2448
|
+
return new Parameter(value, type)
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
function sql(strings, ...args) {
|
|
2452
|
+
const query = strings && Array.isArray(strings.raw)
|
|
2453
|
+
? new Query(strings, args, handler, cancel)
|
|
2454
|
+
: typeof strings === 'string' && !args.length
|
|
2455
|
+
? new Identifier(options.transform.column.to ? options.transform.column.to(strings) : strings)
|
|
2456
|
+
: new Builder(strings, args);
|
|
2457
|
+
return query
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
function unsafe(string, args = [], options = {}) {
|
|
2461
|
+
arguments.length === 2 && !Array.isArray(args) && (options = args, args = []);
|
|
2462
|
+
const query = new Query([string], args, handler, cancel, {
|
|
2463
|
+
prepare: false,
|
|
2464
|
+
...options,
|
|
2465
|
+
simple: 'simple' in options ? options.simple : args.length === 0
|
|
2466
|
+
});
|
|
2467
|
+
return query
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
function file(path, args = [], options = {}) {
|
|
2471
|
+
arguments.length === 2 && !Array.isArray(args) && (options = args, args = []);
|
|
2472
|
+
const query = new Query([], args, (query) => {
|
|
2473
|
+
require$$0.readFile(path, 'utf8', (err, string) => {
|
|
2474
|
+
if (err)
|
|
2475
|
+
return query.reject(err)
|
|
2476
|
+
|
|
2477
|
+
query.strings = [string];
|
|
2478
|
+
handler(query);
|
|
2479
|
+
});
|
|
2480
|
+
}, cancel, {
|
|
2481
|
+
...options,
|
|
2482
|
+
simple: 'simple' in options ? options.simple : args.length === 0
|
|
2483
|
+
});
|
|
2484
|
+
return query
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
async function listen(name, fn, onlisten) {
|
|
2489
|
+
const listener = { fn, onlisten };
|
|
2490
|
+
|
|
2491
|
+
const sql = listen.sql || (listen.sql = Postgres({
|
|
2492
|
+
...options,
|
|
2493
|
+
max: 1,
|
|
2494
|
+
idle_timeout: null,
|
|
2495
|
+
max_lifetime: null,
|
|
2496
|
+
fetch_types: false,
|
|
2497
|
+
onclose() {
|
|
2498
|
+
Object.entries(listen.channels).forEach(([name, { listeners }]) => {
|
|
2499
|
+
delete listen.channels[name];
|
|
2500
|
+
Promise.all(listeners.map(l => listen(name, l.fn, l.onlisten).catch(() => { /* noop */ })));
|
|
2501
|
+
});
|
|
2502
|
+
},
|
|
2503
|
+
onnotify(c, x) {
|
|
2504
|
+
c in listen.channels && listen.channels[c].listeners.forEach(l => l.fn(x));
|
|
2505
|
+
}
|
|
2506
|
+
}));
|
|
2507
|
+
|
|
2508
|
+
const channels = listen.channels || (listen.channels = {})
|
|
2509
|
+
, exists = name in channels;
|
|
2510
|
+
|
|
2511
|
+
if (exists) {
|
|
2512
|
+
channels[name].listeners.push(listener);
|
|
2513
|
+
const result = await channels[name].result;
|
|
2514
|
+
listener.onlisten && listener.onlisten();
|
|
2515
|
+
return { state: result.state, unlisten }
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
channels[name] = { result: sql`listen ${
|
|
2519
|
+
sql.unsafe('"' + name.replace(/"/g, '""') + '"')
|
|
2520
|
+
}`, listeners: [listener] };
|
|
2521
|
+
const result = await channels[name].result;
|
|
2522
|
+
listener.onlisten && listener.onlisten();
|
|
2523
|
+
return { state: result.state, unlisten }
|
|
2524
|
+
|
|
2525
|
+
async function unlisten() {
|
|
2526
|
+
if (name in channels === false)
|
|
2527
|
+
return
|
|
2528
|
+
|
|
2529
|
+
channels[name].listeners = channels[name].listeners.filter(x => x !== listener);
|
|
2530
|
+
if (channels[name].listeners.length)
|
|
2531
|
+
return
|
|
2532
|
+
|
|
2533
|
+
delete channels[name];
|
|
2534
|
+
return sql`unlisten ${
|
|
2535
|
+
sql.unsafe('"' + name.replace(/"/g, '""') + '"')
|
|
2536
|
+
}`
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
async function notify(channel, payload) {
|
|
2541
|
+
return await sql`select pg_notify(${ channel }, ${ '' + payload })`
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
async function reserve() {
|
|
2545
|
+
const queue = Queue();
|
|
2546
|
+
const c = open.length
|
|
2547
|
+
? open.shift()
|
|
2548
|
+
: await new Promise((resolve, reject) => {
|
|
2549
|
+
const query = { reserve: resolve, reject };
|
|
2550
|
+
queries.push(query);
|
|
2551
|
+
closed.length && connect(closed.shift(), query);
|
|
2552
|
+
});
|
|
2553
|
+
|
|
2554
|
+
move(c, reserved);
|
|
2555
|
+
c.reserved = () => queue.length
|
|
2556
|
+
? c.execute(queue.shift())
|
|
2557
|
+
: move(c, reserved);
|
|
2558
|
+
c.reserved.release = true;
|
|
2559
|
+
|
|
2560
|
+
const sql = Sql(handler);
|
|
2561
|
+
sql.release = () => {
|
|
2562
|
+
c.reserved = null;
|
|
2563
|
+
onopen(c);
|
|
2564
|
+
};
|
|
2565
|
+
|
|
2566
|
+
return sql
|
|
2567
|
+
|
|
2568
|
+
function handler(q) {
|
|
2569
|
+
c.queue === full
|
|
2570
|
+
? queue.push(q)
|
|
2571
|
+
: c.execute(q) || move(c, full);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
async function begin(options, fn) {
|
|
2576
|
+
!fn && (fn = options, options = '');
|
|
2577
|
+
const queries = Queue();
|
|
2578
|
+
let savepoints = 0
|
|
2579
|
+
, connection
|
|
2580
|
+
, prepare = null;
|
|
2581
|
+
|
|
2582
|
+
try {
|
|
2583
|
+
await sql.unsafe('begin ' + options.replace(/[^a-z ]/ig, ''), [], { onexecute }).execute();
|
|
2584
|
+
return await Promise.race([
|
|
2585
|
+
scope(connection, fn),
|
|
2586
|
+
new Promise((_, reject) => connection.onclose = reject)
|
|
2587
|
+
])
|
|
2588
|
+
} catch (error) {
|
|
2589
|
+
throw error
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
async function scope(c, fn, name) {
|
|
2593
|
+
const sql = Sql(handler);
|
|
2594
|
+
sql.savepoint = savepoint;
|
|
2595
|
+
sql.prepare = x => prepare = x.replace(/[^a-z0-9$-_. ]/gi);
|
|
2596
|
+
let uncaughtError
|
|
2597
|
+
, result;
|
|
2598
|
+
|
|
2599
|
+
name && await sql`savepoint ${ sql(name) }`;
|
|
2600
|
+
try {
|
|
2601
|
+
result = await new Promise((resolve, reject) => {
|
|
2602
|
+
const x = fn(sql);
|
|
2603
|
+
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve, reject);
|
|
2604
|
+
});
|
|
2605
|
+
|
|
2606
|
+
if (uncaughtError)
|
|
2607
|
+
throw uncaughtError
|
|
2608
|
+
} catch (e) {
|
|
2609
|
+
await (name
|
|
2610
|
+
? sql`rollback to ${ sql(name) }`
|
|
2611
|
+
: sql`rollback`
|
|
2612
|
+
);
|
|
2613
|
+
throw e instanceof PostgresError && e.code === '25P02' && uncaughtError || e
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
if (!name) {
|
|
2617
|
+
prepare
|
|
2618
|
+
? await sql`prepare transaction '${ sql.unsafe(prepare) }'`
|
|
2619
|
+
: await sql`commit`;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
return result
|
|
2623
|
+
|
|
2624
|
+
function savepoint(name, fn) {
|
|
2625
|
+
if (name && Array.isArray(name.raw))
|
|
2626
|
+
return savepoint(sql => sql.apply(sql, arguments))
|
|
2627
|
+
|
|
2628
|
+
arguments.length === 1 && (fn = name, name = null);
|
|
2629
|
+
return scope(c, fn, 's' + savepoints++ + (name ? '_' + name : ''))
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
function handler(q) {
|
|
2633
|
+
q.catch(e => uncaughtError || (uncaughtError = e));
|
|
2634
|
+
c.queue === full
|
|
2635
|
+
? queries.push(q)
|
|
2636
|
+
: c.execute(q) || move(c, full);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
function onexecute(c) {
|
|
2641
|
+
connection = c;
|
|
2642
|
+
move(c, reserved);
|
|
2643
|
+
c.reserved = () => queries.length
|
|
2644
|
+
? c.execute(queries.shift())
|
|
2645
|
+
: move(c, reserved);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
function move(c, queue) {
|
|
2650
|
+
c.queue.remove(c);
|
|
2651
|
+
queue.push(c);
|
|
2652
|
+
c.queue = queue;
|
|
2653
|
+
queue === open
|
|
2654
|
+
? c.idleTimer.start()
|
|
2655
|
+
: c.idleTimer.cancel();
|
|
2656
|
+
return c
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
function json(x) {
|
|
2660
|
+
return new Parameter(x, 3802)
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
function array(x, type) {
|
|
2664
|
+
if (!Array.isArray(x))
|
|
2665
|
+
return array(Array.from(arguments))
|
|
2666
|
+
|
|
2667
|
+
return new Parameter(x, type || (x.length ? inferType(x) || 25 : 0), options.shared.typeArrayMap)
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
function handler(query) {
|
|
2671
|
+
if (ending)
|
|
2672
|
+
return query.reject(Errors.connection('CONNECTION_ENDED', options, options))
|
|
2673
|
+
|
|
2674
|
+
if (open.length)
|
|
2675
|
+
return go(open.shift(), query)
|
|
2676
|
+
|
|
2677
|
+
if (closed.length)
|
|
2678
|
+
return connect(closed.shift(), query)
|
|
2679
|
+
|
|
2680
|
+
busy.length
|
|
2681
|
+
? go(busy.shift(), query)
|
|
2682
|
+
: queries.push(query);
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
function go(c, query) {
|
|
2686
|
+
return c.execute(query)
|
|
2687
|
+
? move(c, busy)
|
|
2688
|
+
: move(c, full)
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
function cancel(query) {
|
|
2692
|
+
return new Promise((resolve, reject) => {
|
|
2693
|
+
query.state
|
|
2694
|
+
? query.active
|
|
2695
|
+
? Connection(options).cancel(query.state, resolve, reject)
|
|
2696
|
+
: query.cancelled = { resolve, reject }
|
|
2697
|
+
: (
|
|
2698
|
+
queries.remove(query),
|
|
2699
|
+
query.cancelled = true,
|
|
2700
|
+
query.reject(Errors.generic('57014', 'canceling statement due to user request')),
|
|
2701
|
+
resolve()
|
|
2702
|
+
);
|
|
2703
|
+
})
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2706
|
+
async function end({ timeout = null } = {}) {
|
|
2707
|
+
if (ending)
|
|
2708
|
+
return ending
|
|
2709
|
+
|
|
2710
|
+
await 1;
|
|
2711
|
+
let timer;
|
|
2712
|
+
return ending = Promise.race([
|
|
2713
|
+
new Promise(r => timeout !== null && (timer = setTimeout(destroy, timeout * 1000, r))),
|
|
2714
|
+
Promise.all(connections.map(c => c.end()).concat(
|
|
2715
|
+
listen.sql ? listen.sql.end({ timeout: 0 }) : [],
|
|
2716
|
+
subscribe.sql ? subscribe.sql.end({ timeout: 0 }) : []
|
|
2717
|
+
))
|
|
2718
|
+
]).then(() => clearTimeout(timer))
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
async function close() {
|
|
2722
|
+
await Promise.all(connections.map(c => c.end()));
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
async function destroy(resolve) {
|
|
2726
|
+
await Promise.all(connections.map(c => c.terminate()));
|
|
2727
|
+
while (queries.length)
|
|
2728
|
+
queries.shift().reject(Errors.connection('CONNECTION_DESTROYED', options));
|
|
2729
|
+
resolve();
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
function connect(c, query) {
|
|
2733
|
+
move(c, connecting);
|
|
2734
|
+
c.connect(query);
|
|
2735
|
+
return c
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
function onend(c) {
|
|
2739
|
+
move(c, ended);
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
function onopen(c) {
|
|
2743
|
+
if (queries.length === 0)
|
|
2744
|
+
return move(c, open)
|
|
2745
|
+
|
|
2746
|
+
let max = Math.ceil(queries.length / (connecting.length + 1))
|
|
2747
|
+
, ready = true;
|
|
2748
|
+
|
|
2749
|
+
while (ready && queries.length && max-- > 0) {
|
|
2750
|
+
const query = queries.shift();
|
|
2751
|
+
if (query.reserve)
|
|
2752
|
+
return query.reserve(c)
|
|
2753
|
+
|
|
2754
|
+
ready = c.execute(query);
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
ready
|
|
2758
|
+
? move(c, busy)
|
|
2759
|
+
: move(c, full);
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
function onclose(c, e) {
|
|
2763
|
+
move(c, closed);
|
|
2764
|
+
c.reserved = null;
|
|
2765
|
+
c.onclose && (c.onclose(e), c.onclose = null);
|
|
2766
|
+
options.onclose && options.onclose(c.id);
|
|
2767
|
+
queries.length && connect(c, queries.shift());
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
function parseOptions(a, b) {
|
|
2772
|
+
if (a && a.shared)
|
|
2773
|
+
return a
|
|
2774
|
+
|
|
2775
|
+
const env = process.env // eslint-disable-line
|
|
2776
|
+
, o = (!a || typeof a === 'string' ? b : a) || {}
|
|
2777
|
+
, { url, multihost } = parseUrl(a)
|
|
2778
|
+
, query = [...url.searchParams].reduce((a, [b, c]) => (a[b] = c, a), {})
|
|
2779
|
+
, host = o.hostname || o.host || multihost || url.hostname || env.PGHOST || 'localhost'
|
|
2780
|
+
, port = o.port || url.port || env.PGPORT || 5432
|
|
2781
|
+
, user = o.user || o.username || url.username || env.PGUSERNAME || env.PGUSER || osUsername();
|
|
2782
|
+
|
|
2783
|
+
o.no_prepare && (o.prepare = false);
|
|
2784
|
+
query.sslmode && (query.ssl = query.sslmode, delete query.sslmode);
|
|
2785
|
+
'timeout' in o && (console.log('The timeout option is deprecated, use idle_timeout instead'), o.idle_timeout = o.timeout); // eslint-disable-line
|
|
2786
|
+
query.sslrootcert === 'system' && (query.ssl = 'verify-full');
|
|
2787
|
+
|
|
2788
|
+
const ints = ['idle_timeout', 'connect_timeout', 'max_lifetime', 'max_pipeline', 'backoff', 'keep_alive'];
|
|
2789
|
+
const defaults = {
|
|
2790
|
+
max : globalThis.Cloudflare ? 3 : 10,
|
|
2791
|
+
ssl : false,
|
|
2792
|
+
sslnegotiation : null,
|
|
2793
|
+
idle_timeout : null,
|
|
2794
|
+
connect_timeout : 30,
|
|
2795
|
+
max_lifetime : max_lifetime,
|
|
2796
|
+
max_pipeline : 100,
|
|
2797
|
+
backoff : backoff,
|
|
2798
|
+
keep_alive : 60,
|
|
2799
|
+
prepare : true,
|
|
2800
|
+
debug : false,
|
|
2801
|
+
fetch_types : true,
|
|
2802
|
+
publications : 'alltables',
|
|
2803
|
+
target_session_attrs: null
|
|
2804
|
+
};
|
|
2805
|
+
|
|
2806
|
+
return {
|
|
2807
|
+
host : Array.isArray(host) ? host : host.split(',').map(x => x.split(':')[0]),
|
|
2808
|
+
port : Array.isArray(port) ? port : host.split(',').map(x => parseInt(x.split(':')[1] || port)),
|
|
2809
|
+
path : o.path || host.indexOf('/') > -1 && host + '/.s.PGSQL.' + port,
|
|
2810
|
+
database : o.database || o.db || (url.pathname || '').slice(1) || env.PGDATABASE || user,
|
|
2811
|
+
user : user,
|
|
2812
|
+
pass : o.pass || o.password || url.password || env.PGPASSWORD || '',
|
|
2813
|
+
...Object.entries(defaults).reduce(
|
|
2814
|
+
(acc, [k, d]) => {
|
|
2815
|
+
const value = k in o ? o[k] : k in query
|
|
2816
|
+
? (query[k] === 'disable' || query[k] === 'false' ? false : query[k])
|
|
2817
|
+
: env['PG' + k.toUpperCase()] || d;
|
|
2818
|
+
acc[k] = typeof value === 'string' && ints.includes(k)
|
|
2819
|
+
? +value
|
|
2820
|
+
: value;
|
|
2821
|
+
return acc
|
|
2822
|
+
},
|
|
2823
|
+
{}
|
|
2824
|
+
),
|
|
2825
|
+
connection : {
|
|
2826
|
+
application_name: env.PGAPPNAME || 'postgres.js',
|
|
2827
|
+
...o.connection,
|
|
2828
|
+
...Object.entries(query).reduce((acc, [k, v]) => (k in defaults || (acc[k] = v), acc), {})
|
|
2829
|
+
},
|
|
2830
|
+
types : o.types || {},
|
|
2831
|
+
target_session_attrs: tsa(o, url, env),
|
|
2832
|
+
onnotice : o.onnotice,
|
|
2833
|
+
onnotify : o.onnotify,
|
|
2834
|
+
onclose : o.onclose,
|
|
2835
|
+
onparameter : o.onparameter,
|
|
2836
|
+
socket : o.socket,
|
|
2837
|
+
transform : parseTransform(o.transform || { undefined: undefined }),
|
|
2838
|
+
parameters : {},
|
|
2839
|
+
shared : { retries: 0, typeArrayMap: {} },
|
|
2840
|
+
...mergeUserTypes(o.types)
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
function tsa(o, url, env) {
|
|
2845
|
+
const x = o.target_session_attrs || url.searchParams.get('target_session_attrs') || env.PGTARGETSESSIONATTRS;
|
|
2846
|
+
if (!x || ['read-write', 'read-only', 'primary', 'standby', 'prefer-standby'].includes(x))
|
|
2847
|
+
return x
|
|
2848
|
+
|
|
2849
|
+
throw new Error('target_session_attrs ' + x + ' is not supported')
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2852
|
+
function backoff(retries) {
|
|
2853
|
+
return (0.5 + Math.random() / 2) * Math.min(3 ** retries / 100, 20)
|
|
2854
|
+
}
|
|
2855
|
+
|
|
2856
|
+
function max_lifetime() {
|
|
2857
|
+
return 60 * (30 + Math.random() * 30)
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
function parseTransform(x) {
|
|
2861
|
+
return {
|
|
2862
|
+
undefined: x.undefined,
|
|
2863
|
+
column: {
|
|
2864
|
+
from: typeof x.column === 'function' ? x.column : x.column && x.column.from,
|
|
2865
|
+
to: x.column && x.column.to
|
|
2866
|
+
},
|
|
2867
|
+
value: {
|
|
2868
|
+
from: typeof x.value === 'function' ? x.value : x.value && x.value.from,
|
|
2869
|
+
to: x.value && x.value.to
|
|
2870
|
+
},
|
|
2871
|
+
row: {
|
|
2872
|
+
from: typeof x.row === 'function' ? x.row : x.row && x.row.from,
|
|
2873
|
+
to: x.row && x.row.to
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
function parseUrl(url) {
|
|
2879
|
+
if (!url || typeof url !== 'string')
|
|
2880
|
+
return { url: { searchParams: new Map() } }
|
|
2881
|
+
|
|
2882
|
+
let host = url;
|
|
2883
|
+
host = host.slice(host.indexOf('://') + 3).split(/[?/]/)[0];
|
|
2884
|
+
host = decodeURIComponent(host.slice(host.indexOf('@') + 1));
|
|
2885
|
+
|
|
2886
|
+
const urlObj = new URL(url.replace(host, host.split(',')[0]));
|
|
2887
|
+
|
|
2888
|
+
return {
|
|
2889
|
+
url: {
|
|
2890
|
+
username: decodeURIComponent(urlObj.username),
|
|
2891
|
+
password: decodeURIComponent(urlObj.password),
|
|
2892
|
+
host: urlObj.host,
|
|
2893
|
+
hostname: urlObj.hostname,
|
|
2894
|
+
port: urlObj.port,
|
|
2895
|
+
pathname: urlObj.pathname,
|
|
2896
|
+
searchParams: urlObj.searchParams
|
|
2897
|
+
},
|
|
2898
|
+
multihost: host.indexOf(',') > -1 && host
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
function osUsername() {
|
|
2903
|
+
try {
|
|
2904
|
+
return os.userInfo().username // eslint-disable-line
|
|
2905
|
+
} catch (_) {
|
|
2906
|
+
return process.env.USERNAME || process.env.USER || process.env.LOGNAME // eslint-disable-line
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
var DatabaseSslMode = /*#__PURE__*/ function(DatabaseSslMode) {
|
|
2911
|
+
DatabaseSslMode["Disable"] = "disable";
|
|
2912
|
+
DatabaseSslMode["Allow"] = "allow";
|
|
2913
|
+
DatabaseSslMode["Prefer"] = "prefer";
|
|
2914
|
+
DatabaseSslMode["Require"] = "require";
|
|
2915
|
+
DatabaseSslMode["VerifyFull"] = "verify-full";
|
|
2916
|
+
return DatabaseSslMode;
|
|
2917
|
+
}({});
|
|
2918
|
+
var ConstraintType = /*#__PURE__*/ function(ConstraintType) {
|
|
2919
|
+
ConstraintType["PRIMARY_KEY"] = "primary-key";
|
|
2920
|
+
ConstraintType["FOREIGN_KEY"] = "foreign-key";
|
|
2921
|
+
ConstraintType["UNIQUE"] = "unique";
|
|
2922
|
+
ConstraintType["CHECK"] = "check";
|
|
2923
|
+
return ConstraintType;
|
|
2924
|
+
}({});
|
|
2925
|
+
var ActionType = /*#__PURE__*/ function(ActionType) {
|
|
2926
|
+
ActionType["NO_ACTION"] = "NO ACTION";
|
|
2927
|
+
ActionType["RESTRICT"] = "RESTRICT";
|
|
2928
|
+
ActionType["CASCADE"] = "CASCADE";
|
|
2929
|
+
ActionType["SET_NULL"] = "SET NULL";
|
|
2930
|
+
ActionType["SET_DEFAULT"] = "SET DEFAULT";
|
|
2931
|
+
return ActionType;
|
|
2932
|
+
}({});
|
|
2933
|
+
var Reason = /*#__PURE__*/ function(Reason) {
|
|
2934
|
+
Reason["MissingInSource"] = "missing in source";
|
|
2935
|
+
Reason["MissingInTarget"] = "missing in target";
|
|
2936
|
+
Reason["Rename"] = "name has changed";
|
|
2937
|
+
return Reason;
|
|
2938
|
+
}({});
|
|
2939
|
+
|
|
2940
|
+
const isPostgresSsl = (ssl)=>typeof ssl !== 'string' || ssl === 'require' || ssl === 'allow' || ssl === 'prefer' || ssl === 'verify-full';
|
|
2941
|
+
const asPostgresConfig = (params)=>{
|
|
2942
|
+
if (params.connectionType === 'parts') {
|
|
2943
|
+
return {
|
|
2944
|
+
host: params.host,
|
|
2945
|
+
port: params.port,
|
|
2946
|
+
username: params.username,
|
|
2947
|
+
password: params.password,
|
|
2948
|
+
database: params.database,
|
|
2949
|
+
ssl: params.ssl === DatabaseSslMode.Disable ? false : params.ssl
|
|
2950
|
+
};
|
|
2951
|
+
}
|
|
2952
|
+
const { host, port, user, password, database, ssl } = parse$1(params.url);
|
|
2953
|
+
if (ssl !== undefined && !isPostgresSsl(ssl)) {
|
|
2954
|
+
throw new Error(`Invalid ssl option: ${ssl}`);
|
|
2955
|
+
}
|
|
2956
|
+
return {
|
|
2957
|
+
host: host ?? undefined,
|
|
2958
|
+
port: port ? Number(port) : undefined,
|
|
2959
|
+
username: user,
|
|
2960
|
+
password,
|
|
2961
|
+
database: database ?? undefined,
|
|
2962
|
+
ssl
|
|
2963
|
+
};
|
|
2964
|
+
};
|
|
2965
|
+
const createPostgres = (options = {})=>{
|
|
2966
|
+
const { connection = {
|
|
2967
|
+
connectionType: 'url',
|
|
2968
|
+
url: 'postgres://postgres:postgres@localhost:5432/postgres'
|
|
2969
|
+
}, maxConnections = 10, timeZone = 'UTC', convertToJsDate = true, convertBigIntToNumber = true, onNotice, onClose } = options;
|
|
2970
|
+
const config = asPostgresConfig(connection);
|
|
2971
|
+
const types = {};
|
|
2972
|
+
if (convertToJsDate) {
|
|
2973
|
+
types.date = {
|
|
2974
|
+
to: 1184,
|
|
2975
|
+
from: [
|
|
2976
|
+
1082,
|
|
2977
|
+
1114,
|
|
2978
|
+
1184
|
|
2979
|
+
],
|
|
2980
|
+
serialize: (x)=>x instanceof Date ? x.toISOString() : x,
|
|
2981
|
+
parse: (x)=>new Date(x)
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
if (convertBigIntToNumber) {
|
|
2985
|
+
types.bigint = {
|
|
2986
|
+
to: 20,
|
|
2987
|
+
from: [
|
|
2988
|
+
20,
|
|
2989
|
+
1700
|
|
2990
|
+
],
|
|
2991
|
+
parse: (value)=>Number.parseInt(value),
|
|
2992
|
+
serialize: (value)=>value.toString()
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
return Postgres({
|
|
2996
|
+
host: config.host,
|
|
2997
|
+
port: config.port,
|
|
2998
|
+
username: config.username,
|
|
2999
|
+
password: config.password,
|
|
3000
|
+
database: config.database,
|
|
3001
|
+
ssl: config.ssl,
|
|
3002
|
+
max: maxConnections,
|
|
3003
|
+
connection: {
|
|
3004
|
+
TimeZone: timeZone
|
|
3005
|
+
},
|
|
3006
|
+
types,
|
|
3007
|
+
onnotice: onNotice,
|
|
3008
|
+
onclose: onClose
|
|
3009
|
+
});
|
|
3010
|
+
};
|
|
3011
|
+
|
|
3
3012
|
const items = [];
|
|
4
3013
|
const register = (item)=>void items.push(item);
|
|
5
3014
|
const getRegisteredItems = ()=>items;
|
|
@@ -576,28 +3585,6 @@ const asFunctionExpression = (options)=>{
|
|
|
576
3585
|
return sql.join('\n ').trim();
|
|
577
3586
|
};
|
|
578
3587
|
|
|
579
|
-
var ConstraintType = /*#__PURE__*/ function(ConstraintType) {
|
|
580
|
-
ConstraintType["PRIMARY_KEY"] = "primary-key";
|
|
581
|
-
ConstraintType["FOREIGN_KEY"] = "foreign-key";
|
|
582
|
-
ConstraintType["UNIQUE"] = "unique";
|
|
583
|
-
ConstraintType["CHECK"] = "check";
|
|
584
|
-
return ConstraintType;
|
|
585
|
-
}({});
|
|
586
|
-
var ActionType = /*#__PURE__*/ function(ActionType) {
|
|
587
|
-
ActionType["NO_ACTION"] = "NO ACTION";
|
|
588
|
-
ActionType["RESTRICT"] = "RESTRICT";
|
|
589
|
-
ActionType["CASCADE"] = "CASCADE";
|
|
590
|
-
ActionType["SET_NULL"] = "SET NULL";
|
|
591
|
-
ActionType["SET_DEFAULT"] = "SET DEFAULT";
|
|
592
|
-
return ActionType;
|
|
593
|
-
}({});
|
|
594
|
-
var Reason = /*#__PURE__*/ function(Reason) {
|
|
595
|
-
Reason["MissingInSource"] = "missing in source";
|
|
596
|
-
Reason["MissingInTarget"] = "missing in target";
|
|
597
|
-
Reason["Rename"] = "name has changed";
|
|
598
|
-
return Reason;
|
|
599
|
-
}({});
|
|
600
|
-
|
|
601
3588
|
const compareEnums = ()=>({
|
|
602
3589
|
onMissing: (source)=>[
|
|
603
3590
|
{
|
|
@@ -18764,27 +21751,23 @@ const readers = [
|
|
|
18764
21751
|
readOverrides
|
|
18765
21752
|
];
|
|
18766
21753
|
|
|
18767
|
-
const isKysely = (db)=>db instanceof Kysely;
|
|
18768
21754
|
/**
|
|
18769
21755
|
* Load schema from a database url
|
|
18770
|
-
*/ const schemaFromDatabase = async (
|
|
18771
|
-
const
|
|
21756
|
+
*/ const schemaFromDatabase = async (options = {})=>{
|
|
21757
|
+
const ctx = new ReaderContext(options);
|
|
21758
|
+
const db = new Kysely({
|
|
18772
21759
|
dialect: new PostgresJSDialect({
|
|
18773
|
-
postgres:
|
|
21760
|
+
postgres: createPostgres(options)
|
|
18774
21761
|
})
|
|
18775
21762
|
});
|
|
18776
|
-
const ctx = new ReaderContext(options);
|
|
18777
21763
|
try {
|
|
18778
21764
|
for (const reader of readers){
|
|
18779
21765
|
await reader(ctx, db);
|
|
18780
21766
|
}
|
|
18781
21767
|
return ctx.build();
|
|
18782
21768
|
} finally{
|
|
18783
|
-
|
|
18784
|
-
if (!isKysely(database)) {
|
|
18785
|
-
await db.destroy();
|
|
18786
|
-
}
|
|
21769
|
+
await db.destroy();
|
|
18787
21770
|
}
|
|
18788
21771
|
};
|
|
18789
21772
|
|
|
18790
|
-
export { ActionType, AfterDeleteTrigger, AfterInsertTrigger, BeforeUpdateTrigger, Check, Column, ConfigurationParameter, ConstraintType, CreateDateColumn, Database, DefaultNamingStrategy, DeleteDateColumn, Extension, Extensions, ForeignKeyColumn, ForeignKeyConstraint, GeneratedColumn, HashNamingStrategy, Index, PrimaryColumn, PrimaryGeneratedColumn, Reason, Table, Trigger, TriggerFunction, Unique, UpdateDateColumn, asHuman, asSql, registerEnum, registerFunction, schemaDiff, schemaDiffToHuman, schemaDiffToSql, schemaFromCode, schemaFromDatabase };
|
|
21773
|
+
export { ActionType, AfterDeleteTrigger, AfterInsertTrigger, BeforeUpdateTrigger, Check, Column, ConfigurationParameter, ConstraintType, CreateDateColumn, Database, DatabaseSslMode, DefaultNamingStrategy, DeleteDateColumn, Extension, Extensions, ForeignKeyColumn, ForeignKeyConstraint, GeneratedColumn, HashNamingStrategy, Index, PrimaryColumn, PrimaryGeneratedColumn, Reason, Table, Trigger, TriggerFunction, Unique, UpdateDateColumn, asHuman, asPostgresConfig, asSql, createPostgres, isPostgresSsl, registerEnum, registerFunction, schemaDiff, schemaDiffToHuman, schemaDiffToSql, schemaFromCode, schemaFromDatabase };
|