opencode-database-plugin 1.0.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/LICENSE +190 -0
- package/README.md +83 -0
- package/dist/__tests__/integration/database.test.d.ts +2 -0
- package/dist/__tests__/integration/database.test.d.ts.map +1 -0
- package/dist/__tests__/integration/setup.d.ts +12 -0
- package/dist/__tests__/integration/setup.d.ts.map +1 -0
- package/dist/__tests__/unit/database.test.d.ts +2 -0
- package/dist/__tests__/unit/database.test.d.ts.map +1 -0
- package/dist/db.d.ts +4 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2492 -0
- package/package.json +54 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2492 @@
|
|
|
1
|
+
// node_modules/postgres/src/index.js
|
|
2
|
+
import os from "os";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
|
|
5
|
+
// node_modules/postgres/src/query.js
|
|
6
|
+
var originCache = new Map;
|
|
7
|
+
var originStackCache = new Map;
|
|
8
|
+
var originError = Symbol("OriginError");
|
|
9
|
+
var CLOSE = {};
|
|
10
|
+
|
|
11
|
+
class Query extends Promise {
|
|
12
|
+
constructor(strings, args, handler, canceller, options = {}) {
|
|
13
|
+
let resolve, reject;
|
|
14
|
+
super((a, b) => {
|
|
15
|
+
resolve = a;
|
|
16
|
+
reject = b;
|
|
17
|
+
});
|
|
18
|
+
this.tagged = Array.isArray(strings.raw);
|
|
19
|
+
this.strings = strings;
|
|
20
|
+
this.args = args;
|
|
21
|
+
this.handler = handler;
|
|
22
|
+
this.canceller = canceller;
|
|
23
|
+
this.options = options;
|
|
24
|
+
this.state = null;
|
|
25
|
+
this.statement = null;
|
|
26
|
+
this.resolve = (x) => (this.active = false, resolve(x));
|
|
27
|
+
this.reject = (x) => (this.active = false, reject(x));
|
|
28
|
+
this.active = false;
|
|
29
|
+
this.cancelled = null;
|
|
30
|
+
this.executed = false;
|
|
31
|
+
this.signature = "";
|
|
32
|
+
this[originError] = this.handler.debug ? new Error : this.tagged && cachedError(this.strings);
|
|
33
|
+
}
|
|
34
|
+
get origin() {
|
|
35
|
+
return (this.handler.debug ? this[originError].stack : this.tagged && originStackCache.has(this.strings) ? originStackCache.get(this.strings) : originStackCache.set(this.strings, this[originError].stack).get(this.strings)) || "";
|
|
36
|
+
}
|
|
37
|
+
static get [Symbol.species]() {
|
|
38
|
+
return Promise;
|
|
39
|
+
}
|
|
40
|
+
cancel() {
|
|
41
|
+
return this.canceller && (this.canceller(this), this.canceller = null);
|
|
42
|
+
}
|
|
43
|
+
simple() {
|
|
44
|
+
this.options.simple = true;
|
|
45
|
+
this.options.prepare = false;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
async readable() {
|
|
49
|
+
this.simple();
|
|
50
|
+
this.streaming = true;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
async writable() {
|
|
54
|
+
this.simple();
|
|
55
|
+
this.streaming = true;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
cursor(rows = 1, fn) {
|
|
59
|
+
this.options.simple = false;
|
|
60
|
+
if (typeof rows === "function") {
|
|
61
|
+
fn = rows;
|
|
62
|
+
rows = 1;
|
|
63
|
+
}
|
|
64
|
+
this.cursorRows = rows;
|
|
65
|
+
if (typeof fn === "function")
|
|
66
|
+
return this.cursorFn = fn, this;
|
|
67
|
+
let prev;
|
|
68
|
+
return {
|
|
69
|
+
[Symbol.asyncIterator]: () => ({
|
|
70
|
+
next: () => {
|
|
71
|
+
if (this.executed && !this.active)
|
|
72
|
+
return { done: true };
|
|
73
|
+
prev && prev();
|
|
74
|
+
const promise = new Promise((resolve, reject) => {
|
|
75
|
+
this.cursorFn = (value) => {
|
|
76
|
+
resolve({ value, done: false });
|
|
77
|
+
return new Promise((r) => prev = r);
|
|
78
|
+
};
|
|
79
|
+
this.resolve = () => (this.active = false, resolve({ done: true }));
|
|
80
|
+
this.reject = (x) => (this.active = false, reject(x));
|
|
81
|
+
});
|
|
82
|
+
this.execute();
|
|
83
|
+
return promise;
|
|
84
|
+
},
|
|
85
|
+
return() {
|
|
86
|
+
prev && prev(CLOSE);
|
|
87
|
+
return { done: true };
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
describe() {
|
|
93
|
+
this.options.simple = false;
|
|
94
|
+
this.onlyDescribe = this.options.prepare = true;
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
stream() {
|
|
98
|
+
throw new Error(".stream has been renamed to .forEach");
|
|
99
|
+
}
|
|
100
|
+
forEach(fn) {
|
|
101
|
+
this.forEachFn = fn;
|
|
102
|
+
this.handle();
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
raw() {
|
|
106
|
+
this.isRaw = true;
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
values() {
|
|
110
|
+
this.isRaw = "values";
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
async handle() {
|
|
114
|
+
!this.executed && (this.executed = true) && await 1 && this.handler(this);
|
|
115
|
+
}
|
|
116
|
+
execute() {
|
|
117
|
+
this.handle();
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
then() {
|
|
121
|
+
this.handle();
|
|
122
|
+
return super.then.apply(this, arguments);
|
|
123
|
+
}
|
|
124
|
+
catch() {
|
|
125
|
+
this.handle();
|
|
126
|
+
return super.catch.apply(this, arguments);
|
|
127
|
+
}
|
|
128
|
+
finally() {
|
|
129
|
+
this.handle();
|
|
130
|
+
return super.finally.apply(this, arguments);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function cachedError(xs) {
|
|
134
|
+
if (originCache.has(xs))
|
|
135
|
+
return originCache.get(xs);
|
|
136
|
+
const x = Error.stackTraceLimit;
|
|
137
|
+
Error.stackTraceLimit = 4;
|
|
138
|
+
originCache.set(xs, new Error);
|
|
139
|
+
Error.stackTraceLimit = x;
|
|
140
|
+
return originCache.get(xs);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// node_modules/postgres/src/errors.js
|
|
144
|
+
class PostgresError extends Error {
|
|
145
|
+
constructor(x) {
|
|
146
|
+
super(x.message);
|
|
147
|
+
this.name = this.constructor.name;
|
|
148
|
+
Object.assign(this, x);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
var Errors = {
|
|
152
|
+
connection,
|
|
153
|
+
postgres,
|
|
154
|
+
generic,
|
|
155
|
+
notSupported
|
|
156
|
+
};
|
|
157
|
+
function connection(x, options, socket) {
|
|
158
|
+
const { host, port } = socket || options;
|
|
159
|
+
const error = Object.assign(new Error("write " + x + " " + (options.path || host + ":" + port)), {
|
|
160
|
+
code: x,
|
|
161
|
+
errno: x,
|
|
162
|
+
address: options.path || host
|
|
163
|
+
}, options.path ? {} : { port });
|
|
164
|
+
Error.captureStackTrace(error, connection);
|
|
165
|
+
return error;
|
|
166
|
+
}
|
|
167
|
+
function postgres(x) {
|
|
168
|
+
const error = new PostgresError(x);
|
|
169
|
+
Error.captureStackTrace(error, postgres);
|
|
170
|
+
return error;
|
|
171
|
+
}
|
|
172
|
+
function generic(code, message) {
|
|
173
|
+
const error = Object.assign(new Error(code + ": " + message), { code });
|
|
174
|
+
Error.captureStackTrace(error, generic);
|
|
175
|
+
return error;
|
|
176
|
+
}
|
|
177
|
+
function notSupported(x) {
|
|
178
|
+
const error = Object.assign(new Error(x + " (B) is not supported"), {
|
|
179
|
+
code: "MESSAGE_NOT_SUPPORTED",
|
|
180
|
+
name: x
|
|
181
|
+
});
|
|
182
|
+
Error.captureStackTrace(error, notSupported);
|
|
183
|
+
return error;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// node_modules/postgres/src/types.js
|
|
187
|
+
var types = {
|
|
188
|
+
string: {
|
|
189
|
+
to: 25,
|
|
190
|
+
from: null,
|
|
191
|
+
serialize: (x) => "" + x
|
|
192
|
+
},
|
|
193
|
+
number: {
|
|
194
|
+
to: 0,
|
|
195
|
+
from: [21, 23, 26, 700, 701],
|
|
196
|
+
serialize: (x) => "" + x,
|
|
197
|
+
parse: (x) => +x
|
|
198
|
+
},
|
|
199
|
+
json: {
|
|
200
|
+
to: 114,
|
|
201
|
+
from: [114, 3802],
|
|
202
|
+
serialize: (x) => JSON.stringify(x),
|
|
203
|
+
parse: (x) => JSON.parse(x)
|
|
204
|
+
},
|
|
205
|
+
boolean: {
|
|
206
|
+
to: 16,
|
|
207
|
+
from: 16,
|
|
208
|
+
serialize: (x) => x === true ? "t" : "f",
|
|
209
|
+
parse: (x) => x === "t"
|
|
210
|
+
},
|
|
211
|
+
date: {
|
|
212
|
+
to: 1184,
|
|
213
|
+
from: [1082, 1114, 1184],
|
|
214
|
+
serialize: (x) => (x instanceof Date ? x : new Date(x)).toISOString(),
|
|
215
|
+
parse: (x) => new Date(x)
|
|
216
|
+
},
|
|
217
|
+
bytea: {
|
|
218
|
+
to: 17,
|
|
219
|
+
from: 17,
|
|
220
|
+
serialize: (x) => "\\x" + Buffer.from(x).toString("hex"),
|
|
221
|
+
parse: (x) => Buffer.from(x.slice(2), "hex")
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
class NotTagged {
|
|
226
|
+
then() {
|
|
227
|
+
notTagged();
|
|
228
|
+
}
|
|
229
|
+
catch() {
|
|
230
|
+
notTagged();
|
|
231
|
+
}
|
|
232
|
+
finally() {
|
|
233
|
+
notTagged();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
class Identifier extends NotTagged {
|
|
238
|
+
constructor(value) {
|
|
239
|
+
super();
|
|
240
|
+
this.value = escapeIdentifier(value);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
class Parameter extends NotTagged {
|
|
245
|
+
constructor(value, type, array) {
|
|
246
|
+
super();
|
|
247
|
+
this.value = value;
|
|
248
|
+
this.type = type;
|
|
249
|
+
this.array = array;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
class Builder extends NotTagged {
|
|
254
|
+
constructor(first, rest) {
|
|
255
|
+
super();
|
|
256
|
+
this.first = first;
|
|
257
|
+
this.rest = rest;
|
|
258
|
+
}
|
|
259
|
+
build(before, parameters, types2, options) {
|
|
260
|
+
const keyword = builders.map(([x, fn]) => ({ fn, i: before.search(x) })).sort((a, b) => a.i - b.i).pop();
|
|
261
|
+
return keyword.i === -1 ? escapeIdentifiers(this.first, options) : keyword.fn(this.first, this.rest, parameters, types2, options);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function handleValue(x, parameters, types2, options) {
|
|
265
|
+
let value = x instanceof Parameter ? x.value : x;
|
|
266
|
+
if (value === undefined) {
|
|
267
|
+
x instanceof Parameter ? x.value = options.transform.undefined : value = x = options.transform.undefined;
|
|
268
|
+
if (value === undefined)
|
|
269
|
+
throw Errors.generic("UNDEFINED_VALUE", "Undefined values are not allowed");
|
|
270
|
+
}
|
|
271
|
+
return "$" + types2.push(x instanceof Parameter ? (parameters.push(x.value), x.array ? x.array[x.type || inferType(x.value)] || x.type || firstIsString(x.value) : x.type) : (parameters.push(x), inferType(x)));
|
|
272
|
+
}
|
|
273
|
+
var defaultHandlers = typeHandlers(types);
|
|
274
|
+
function stringify(q, string, value, parameters, types2, options) {
|
|
275
|
+
for (let i = 1;i < q.strings.length; i++) {
|
|
276
|
+
string += stringifyValue(string, value, parameters, types2, options) + q.strings[i];
|
|
277
|
+
value = q.args[i];
|
|
278
|
+
}
|
|
279
|
+
return string;
|
|
280
|
+
}
|
|
281
|
+
function stringifyValue(string, value, parameters, types2, o) {
|
|
282
|
+
return value instanceof Builder ? value.build(string, parameters, types2, o) : value instanceof Query ? fragment(value, parameters, types2, o) : value instanceof Identifier ? value.value : value && value[0] instanceof Query ? value.reduce((acc, x) => acc + " " + fragment(x, parameters, types2, o), "") : handleValue(value, parameters, types2, o);
|
|
283
|
+
}
|
|
284
|
+
function fragment(q, parameters, types2, options) {
|
|
285
|
+
q.fragment = true;
|
|
286
|
+
return stringify(q, q.strings[0], q.args[0], parameters, types2, options);
|
|
287
|
+
}
|
|
288
|
+
function valuesBuilder(first, parameters, types2, columns, options) {
|
|
289
|
+
return first.map((row) => "(" + columns.map((column) => stringifyValue("values", row[column], parameters, types2, options)).join(",") + ")").join(",");
|
|
290
|
+
}
|
|
291
|
+
function values(first, rest, parameters, types2, options) {
|
|
292
|
+
const multi = Array.isArray(first[0]);
|
|
293
|
+
const columns = rest.length ? rest.flat() : Object.keys(multi ? first[0] : first);
|
|
294
|
+
return valuesBuilder(multi ? first : [first], parameters, types2, columns, options);
|
|
295
|
+
}
|
|
296
|
+
function select(first, rest, parameters, types2, options) {
|
|
297
|
+
typeof first === "string" && (first = [first].concat(rest));
|
|
298
|
+
if (Array.isArray(first))
|
|
299
|
+
return escapeIdentifiers(first, options);
|
|
300
|
+
let value;
|
|
301
|
+
const columns = rest.length ? rest.flat() : Object.keys(first);
|
|
302
|
+
return columns.map((x) => {
|
|
303
|
+
value = first[x];
|
|
304
|
+
return (value instanceof Query ? fragment(value, parameters, types2, options) : value instanceof Identifier ? value.value : handleValue(value, parameters, types2, options)) + " as " + escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x);
|
|
305
|
+
}).join(",");
|
|
306
|
+
}
|
|
307
|
+
var builders = Object.entries({
|
|
308
|
+
values,
|
|
309
|
+
in: (...xs) => {
|
|
310
|
+
const x = values(...xs);
|
|
311
|
+
return x === "()" ? "(null)" : x;
|
|
312
|
+
},
|
|
313
|
+
select,
|
|
314
|
+
as: select,
|
|
315
|
+
returning: select,
|
|
316
|
+
"\\(": select,
|
|
317
|
+
update(first, rest, parameters, types2, options) {
|
|
318
|
+
return (rest.length ? rest.flat() : Object.keys(first)).map((x) => escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x) + "=" + stringifyValue("values", first[x], parameters, types2, options));
|
|
319
|
+
},
|
|
320
|
+
insert(first, rest, parameters, types2, options) {
|
|
321
|
+
const columns = rest.length ? rest.flat() : Object.keys(Array.isArray(first) ? first[0] : first);
|
|
322
|
+
return "(" + escapeIdentifiers(columns, options) + ")values" + valuesBuilder(Array.isArray(first) ? first : [first], parameters, types2, columns, options);
|
|
323
|
+
}
|
|
324
|
+
}).map(([x, fn]) => [new RegExp("((?:^|[\\s(])" + x + "(?:$|[\\s(]))(?![\\s\\S]*\\1)", "i"), fn]);
|
|
325
|
+
function notTagged() {
|
|
326
|
+
throw Errors.generic("NOT_TAGGED_CALL", "Query not called as a tagged template literal");
|
|
327
|
+
}
|
|
328
|
+
var serializers = defaultHandlers.serializers;
|
|
329
|
+
var parsers = defaultHandlers.parsers;
|
|
330
|
+
function firstIsString(x) {
|
|
331
|
+
if (Array.isArray(x))
|
|
332
|
+
return firstIsString(x[0]);
|
|
333
|
+
return typeof x === "string" ? 1009 : 0;
|
|
334
|
+
}
|
|
335
|
+
var mergeUserTypes = function(types2) {
|
|
336
|
+
const user = typeHandlers(types2 || {});
|
|
337
|
+
return {
|
|
338
|
+
serializers: Object.assign({}, serializers, user.serializers),
|
|
339
|
+
parsers: Object.assign({}, parsers, user.parsers)
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
function typeHandlers(types2) {
|
|
343
|
+
return Object.keys(types2).reduce((acc, k) => {
|
|
344
|
+
types2[k].from && [].concat(types2[k].from).forEach((x) => acc.parsers[x] = types2[k].parse);
|
|
345
|
+
if (types2[k].serialize) {
|
|
346
|
+
acc.serializers[types2[k].to] = types2[k].serialize;
|
|
347
|
+
types2[k].from && [].concat(types2[k].from).forEach((x) => acc.serializers[x] = types2[k].serialize);
|
|
348
|
+
}
|
|
349
|
+
return acc;
|
|
350
|
+
}, { parsers: {}, serializers: {} });
|
|
351
|
+
}
|
|
352
|
+
function escapeIdentifiers(xs, { transform: { column } }) {
|
|
353
|
+
return xs.map((x) => escapeIdentifier(column.to ? column.to(x) : x)).join(",");
|
|
354
|
+
}
|
|
355
|
+
var escapeIdentifier = function escape(str) {
|
|
356
|
+
return '"' + str.replace(/"/g, '""').replace(/\./g, '"."') + '"';
|
|
357
|
+
};
|
|
358
|
+
var inferType = function inferType2(x) {
|
|
359
|
+
return x instanceof Parameter ? x.type : x instanceof Date ? 1184 : x instanceof Uint8Array ? 17 : x === true || x === false ? 16 : typeof x === "bigint" ? 20 : Array.isArray(x) ? inferType2(x[0]) : 0;
|
|
360
|
+
};
|
|
361
|
+
var escapeBackslash = /\\/g;
|
|
362
|
+
var escapeQuote = /"/g;
|
|
363
|
+
function arrayEscape(x) {
|
|
364
|
+
return x.replace(escapeBackslash, "\\\\").replace(escapeQuote, "\\\"");
|
|
365
|
+
}
|
|
366
|
+
var arraySerializer = function arraySerializer2(xs, serializer, options, typarray) {
|
|
367
|
+
if (Array.isArray(xs) === false)
|
|
368
|
+
return xs;
|
|
369
|
+
if (!xs.length)
|
|
370
|
+
return "{}";
|
|
371
|
+
const first = xs[0];
|
|
372
|
+
const delimiter = typarray === 1020 ? ";" : ",";
|
|
373
|
+
if (Array.isArray(first) && !first.type)
|
|
374
|
+
return "{" + xs.map((x) => arraySerializer2(x, serializer, options, typarray)).join(delimiter) + "}";
|
|
375
|
+
return "{" + xs.map((x) => {
|
|
376
|
+
if (x === undefined) {
|
|
377
|
+
x = options.transform.undefined;
|
|
378
|
+
if (x === undefined)
|
|
379
|
+
throw Errors.generic("UNDEFINED_VALUE", "Undefined values are not allowed");
|
|
380
|
+
}
|
|
381
|
+
return x === null ? "null" : '"' + arrayEscape(serializer ? serializer(x.type ? x.value : x) : "" + x) + '"';
|
|
382
|
+
}).join(delimiter) + "}";
|
|
383
|
+
};
|
|
384
|
+
var arrayParserState = {
|
|
385
|
+
i: 0,
|
|
386
|
+
char: null,
|
|
387
|
+
str: "",
|
|
388
|
+
quoted: false,
|
|
389
|
+
last: 0
|
|
390
|
+
};
|
|
391
|
+
var arrayParser = function arrayParser2(x, parser, typarray) {
|
|
392
|
+
arrayParserState.i = arrayParserState.last = 0;
|
|
393
|
+
return arrayParserLoop(arrayParserState, x, parser, typarray);
|
|
394
|
+
};
|
|
395
|
+
function arrayParserLoop(s, x, parser, typarray) {
|
|
396
|
+
const xs = [];
|
|
397
|
+
const delimiter = typarray === 1020 ? ";" : ",";
|
|
398
|
+
for (;s.i < x.length; s.i++) {
|
|
399
|
+
s.char = x[s.i];
|
|
400
|
+
if (s.quoted) {
|
|
401
|
+
if (s.char === "\\") {
|
|
402
|
+
s.str += x[++s.i];
|
|
403
|
+
} else if (s.char === '"') {
|
|
404
|
+
xs.push(parser ? parser(s.str) : s.str);
|
|
405
|
+
s.str = "";
|
|
406
|
+
s.quoted = x[s.i + 1] === '"';
|
|
407
|
+
s.last = s.i + 2;
|
|
408
|
+
} else {
|
|
409
|
+
s.str += s.char;
|
|
410
|
+
}
|
|
411
|
+
} else if (s.char === '"') {
|
|
412
|
+
s.quoted = true;
|
|
413
|
+
} else if (s.char === "{") {
|
|
414
|
+
s.last = ++s.i;
|
|
415
|
+
xs.push(arrayParserLoop(s, x, parser, typarray));
|
|
416
|
+
} else if (s.char === "}") {
|
|
417
|
+
s.quoted = false;
|
|
418
|
+
s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i));
|
|
419
|
+
s.last = s.i + 1;
|
|
420
|
+
break;
|
|
421
|
+
} else if (s.char === delimiter && s.p !== "}" && s.p !== '"') {
|
|
422
|
+
xs.push(parser ? parser(x.slice(s.last, s.i)) : x.slice(s.last, s.i));
|
|
423
|
+
s.last = s.i + 1;
|
|
424
|
+
}
|
|
425
|
+
s.p = s.char;
|
|
426
|
+
}
|
|
427
|
+
s.last < s.i && xs.push(parser ? parser(x.slice(s.last, s.i + 1)) : x.slice(s.last, s.i + 1));
|
|
428
|
+
return xs;
|
|
429
|
+
}
|
|
430
|
+
var toCamel = (x) => {
|
|
431
|
+
let str = x[0];
|
|
432
|
+
for (let i = 1;i < x.length; i++)
|
|
433
|
+
str += x[i] === "_" ? x[++i].toUpperCase() : x[i];
|
|
434
|
+
return str;
|
|
435
|
+
};
|
|
436
|
+
var toPascal = (x) => {
|
|
437
|
+
let str = x[0].toUpperCase();
|
|
438
|
+
for (let i = 1;i < x.length; i++)
|
|
439
|
+
str += x[i] === "_" ? x[++i].toUpperCase() : x[i];
|
|
440
|
+
return str;
|
|
441
|
+
};
|
|
442
|
+
var toKebab = (x) => x.replace(/_/g, "-");
|
|
443
|
+
var fromCamel = (x) => x.replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
444
|
+
var fromPascal = (x) => (x.slice(0, 1) + x.slice(1).replace(/([A-Z])/g, "_$1")).toLowerCase();
|
|
445
|
+
var fromKebab = (x) => x.replace(/-/g, "_");
|
|
446
|
+
function createJsonTransform(fn) {
|
|
447
|
+
return function jsonTransform(x, column) {
|
|
448
|
+
return typeof x === "object" && x !== null && (column.type === 114 || column.type === 3802) ? Array.isArray(x) ? x.map((x2) => jsonTransform(x2, column)) : Object.entries(x).reduce((acc, [k, v]) => Object.assign(acc, { [fn(k)]: jsonTransform(v, column) }), {}) : x;
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
toCamel.column = { from: toCamel };
|
|
452
|
+
toCamel.value = { from: createJsonTransform(toCamel) };
|
|
453
|
+
fromCamel.column = { to: fromCamel };
|
|
454
|
+
var camel = { ...toCamel };
|
|
455
|
+
camel.column.to = fromCamel;
|
|
456
|
+
toPascal.column = { from: toPascal };
|
|
457
|
+
toPascal.value = { from: createJsonTransform(toPascal) };
|
|
458
|
+
fromPascal.column = { to: fromPascal };
|
|
459
|
+
var pascal = { ...toPascal };
|
|
460
|
+
pascal.column.to = fromPascal;
|
|
461
|
+
toKebab.column = { from: toKebab };
|
|
462
|
+
toKebab.value = { from: createJsonTransform(toKebab) };
|
|
463
|
+
fromKebab.column = { to: fromKebab };
|
|
464
|
+
var kebab = { ...toKebab };
|
|
465
|
+
kebab.column.to = fromKebab;
|
|
466
|
+
|
|
467
|
+
// node_modules/postgres/src/connection.js
|
|
468
|
+
import net from "net";
|
|
469
|
+
import tls from "tls";
|
|
470
|
+
import crypto from "crypto";
|
|
471
|
+
import Stream from "stream";
|
|
472
|
+
import { performance } from "perf_hooks";
|
|
473
|
+
|
|
474
|
+
// node_modules/postgres/src/result.js
|
|
475
|
+
class Result extends Array {
|
|
476
|
+
constructor() {
|
|
477
|
+
super();
|
|
478
|
+
Object.defineProperties(this, {
|
|
479
|
+
count: { value: null, writable: true },
|
|
480
|
+
state: { value: null, writable: true },
|
|
481
|
+
command: { value: null, writable: true },
|
|
482
|
+
columns: { value: null, writable: true },
|
|
483
|
+
statement: { value: null, writable: true }
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
static get [Symbol.species]() {
|
|
487
|
+
return Array;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// node_modules/postgres/src/queue.js
|
|
492
|
+
var queue_default = Queue;
|
|
493
|
+
function Queue(initial = []) {
|
|
494
|
+
let xs = initial.slice();
|
|
495
|
+
let index = 0;
|
|
496
|
+
return {
|
|
497
|
+
get length() {
|
|
498
|
+
return xs.length - index;
|
|
499
|
+
},
|
|
500
|
+
remove: (x) => {
|
|
501
|
+
const index2 = xs.indexOf(x);
|
|
502
|
+
return index2 === -1 ? null : (xs.splice(index2, 1), x);
|
|
503
|
+
},
|
|
504
|
+
push: (x) => (xs.push(x), x),
|
|
505
|
+
shift: () => {
|
|
506
|
+
const out = xs[index++];
|
|
507
|
+
if (index === xs.length) {
|
|
508
|
+
index = 0;
|
|
509
|
+
xs = [];
|
|
510
|
+
} else {
|
|
511
|
+
xs[index - 1] = undefined;
|
|
512
|
+
}
|
|
513
|
+
return out;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// node_modules/postgres/src/bytes.js
|
|
519
|
+
var size = 256;
|
|
520
|
+
var buffer = Buffer.allocUnsafe(size);
|
|
521
|
+
var messages = "BCcDdEFfHPpQSX".split("").reduce((acc, x) => {
|
|
522
|
+
const v = x.charCodeAt(0);
|
|
523
|
+
acc[x] = () => {
|
|
524
|
+
buffer[0] = v;
|
|
525
|
+
b.i = 5;
|
|
526
|
+
return b;
|
|
527
|
+
};
|
|
528
|
+
return acc;
|
|
529
|
+
}, {});
|
|
530
|
+
var b = Object.assign(reset, messages, {
|
|
531
|
+
N: String.fromCharCode(0),
|
|
532
|
+
i: 0,
|
|
533
|
+
inc(x) {
|
|
534
|
+
b.i += x;
|
|
535
|
+
return b;
|
|
536
|
+
},
|
|
537
|
+
str(x) {
|
|
538
|
+
const length = Buffer.byteLength(x);
|
|
539
|
+
fit(length);
|
|
540
|
+
b.i += buffer.write(x, b.i, length, "utf8");
|
|
541
|
+
return b;
|
|
542
|
+
},
|
|
543
|
+
i16(x) {
|
|
544
|
+
fit(2);
|
|
545
|
+
buffer.writeUInt16BE(x, b.i);
|
|
546
|
+
b.i += 2;
|
|
547
|
+
return b;
|
|
548
|
+
},
|
|
549
|
+
i32(x, i) {
|
|
550
|
+
if (i || i === 0) {
|
|
551
|
+
buffer.writeUInt32BE(x, i);
|
|
552
|
+
return b;
|
|
553
|
+
}
|
|
554
|
+
fit(4);
|
|
555
|
+
buffer.writeUInt32BE(x, b.i);
|
|
556
|
+
b.i += 4;
|
|
557
|
+
return b;
|
|
558
|
+
},
|
|
559
|
+
z(x) {
|
|
560
|
+
fit(x);
|
|
561
|
+
buffer.fill(0, b.i, b.i + x);
|
|
562
|
+
b.i += x;
|
|
563
|
+
return b;
|
|
564
|
+
},
|
|
565
|
+
raw(x) {
|
|
566
|
+
buffer = Buffer.concat([buffer.subarray(0, b.i), x]);
|
|
567
|
+
b.i = buffer.length;
|
|
568
|
+
return b;
|
|
569
|
+
},
|
|
570
|
+
end(at = 1) {
|
|
571
|
+
buffer.writeUInt32BE(b.i - at, at);
|
|
572
|
+
const out = buffer.subarray(0, b.i);
|
|
573
|
+
b.i = 0;
|
|
574
|
+
buffer = Buffer.allocUnsafe(size);
|
|
575
|
+
return out;
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
var bytes_default = b;
|
|
579
|
+
function fit(x) {
|
|
580
|
+
if (buffer.length - b.i < x) {
|
|
581
|
+
const prev = buffer, length = prev.length;
|
|
582
|
+
buffer = Buffer.allocUnsafe(length + (length >> 1) + x);
|
|
583
|
+
prev.copy(buffer);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
function reset() {
|
|
587
|
+
b.i = 0;
|
|
588
|
+
return b;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// node_modules/postgres/src/connection.js
|
|
592
|
+
var connection_default = Connection;
|
|
593
|
+
var uid = 1;
|
|
594
|
+
var Sync = bytes_default().S().end();
|
|
595
|
+
var Flush = bytes_default().H().end();
|
|
596
|
+
var SSLRequest = bytes_default().i32(8).i32(80877103).end(8);
|
|
597
|
+
var ExecuteUnnamed = Buffer.concat([bytes_default().E().str(bytes_default.N).i32(0).end(), Sync]);
|
|
598
|
+
var DescribeUnnamed = bytes_default().D().str("S").str(bytes_default.N).end();
|
|
599
|
+
var noop = () => {};
|
|
600
|
+
var retryRoutines = new Set([
|
|
601
|
+
"FetchPreparedStatement",
|
|
602
|
+
"RevalidateCachedQuery",
|
|
603
|
+
"transformAssignedExpr"
|
|
604
|
+
]);
|
|
605
|
+
var errorFields = {
|
|
606
|
+
83: "severity_local",
|
|
607
|
+
86: "severity",
|
|
608
|
+
67: "code",
|
|
609
|
+
77: "message",
|
|
610
|
+
68: "detail",
|
|
611
|
+
72: "hint",
|
|
612
|
+
80: "position",
|
|
613
|
+
112: "internal_position",
|
|
614
|
+
113: "internal_query",
|
|
615
|
+
87: "where",
|
|
616
|
+
115: "schema_name",
|
|
617
|
+
116: "table_name",
|
|
618
|
+
99: "column_name",
|
|
619
|
+
100: "data type_name",
|
|
620
|
+
110: "constraint_name",
|
|
621
|
+
70: "file",
|
|
622
|
+
76: "line",
|
|
623
|
+
82: "routine"
|
|
624
|
+
};
|
|
625
|
+
function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose = noop } = {}) {
|
|
626
|
+
const {
|
|
627
|
+
ssl,
|
|
628
|
+
max,
|
|
629
|
+
user,
|
|
630
|
+
host,
|
|
631
|
+
port,
|
|
632
|
+
database,
|
|
633
|
+
parsers: parsers2,
|
|
634
|
+
transform,
|
|
635
|
+
onnotice,
|
|
636
|
+
onnotify,
|
|
637
|
+
onparameter,
|
|
638
|
+
max_pipeline,
|
|
639
|
+
keep_alive,
|
|
640
|
+
backoff,
|
|
641
|
+
target_session_attrs
|
|
642
|
+
} = options;
|
|
643
|
+
const sent = queue_default(), id = uid++, backend = { pid: null, secret: null }, idleTimer = timer(end, options.idle_timeout), lifeTimer = timer(end, options.max_lifetime), connectTimer = timer(connectTimedOut, options.connect_timeout);
|
|
644
|
+
let socket = null, cancelMessage, result = new Result, incoming = Buffer.alloc(0), needsTypes = options.fetch_types, backendParameters = {}, statements = {}, statementId = Math.random().toString(36).slice(2), statementCount = 1, closedDate = 0, remaining = 0, hostIndex = 0, retries = 0, length = 0, delay = 0, rows = 0, serverSignature = null, nextWriteTimer = null, terminated = false, incomings = null, results = null, initial = null, ending = null, stream = null, chunk = null, ended = null, nonce = null, query = null, final = null;
|
|
645
|
+
const connection2 = {
|
|
646
|
+
queue: queues.closed,
|
|
647
|
+
idleTimer,
|
|
648
|
+
connect(query2) {
|
|
649
|
+
initial = query2;
|
|
650
|
+
reconnect();
|
|
651
|
+
},
|
|
652
|
+
terminate,
|
|
653
|
+
execute,
|
|
654
|
+
cancel,
|
|
655
|
+
end,
|
|
656
|
+
count: 0,
|
|
657
|
+
id
|
|
658
|
+
};
|
|
659
|
+
queues.closed && queues.closed.push(connection2);
|
|
660
|
+
return connection2;
|
|
661
|
+
async function createSocket() {
|
|
662
|
+
let x;
|
|
663
|
+
try {
|
|
664
|
+
x = options.socket ? await Promise.resolve(options.socket(options)) : new net.Socket;
|
|
665
|
+
} catch (e) {
|
|
666
|
+
error(e);
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
x.on("error", error);
|
|
670
|
+
x.on("close", closed);
|
|
671
|
+
x.on("drain", drain);
|
|
672
|
+
return x;
|
|
673
|
+
}
|
|
674
|
+
async function cancel({ pid, secret }, resolve, reject) {
|
|
675
|
+
try {
|
|
676
|
+
cancelMessage = bytes_default().i32(16).i32(80877102).i32(pid).i32(secret).end(16);
|
|
677
|
+
await connect();
|
|
678
|
+
socket.once("error", reject);
|
|
679
|
+
socket.once("close", resolve);
|
|
680
|
+
} catch (error2) {
|
|
681
|
+
reject(error2);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function execute(q) {
|
|
685
|
+
if (terminated)
|
|
686
|
+
return queryError(q, Errors.connection("CONNECTION_DESTROYED", options));
|
|
687
|
+
if (q.cancelled)
|
|
688
|
+
return;
|
|
689
|
+
try {
|
|
690
|
+
q.state = backend;
|
|
691
|
+
query ? sent.push(q) : (query = q, query.active = true);
|
|
692
|
+
build(q);
|
|
693
|
+
return write(toBuffer(q)) && !q.describeFirst && !q.cursorFn && sent.length < max_pipeline && (!q.options.onexecute || q.options.onexecute(connection2));
|
|
694
|
+
} catch (error2) {
|
|
695
|
+
sent.length === 0 && write(Sync);
|
|
696
|
+
errored(error2);
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
function toBuffer(q) {
|
|
701
|
+
if (q.parameters.length >= 65534)
|
|
702
|
+
throw Errors.generic("MAX_PARAMETERS_EXCEEDED", "Max number of parameters (65534) exceeded");
|
|
703
|
+
return q.options.simple ? bytes_default().Q().str(q.statement.string + bytes_default.N).end() : q.describeFirst ? Buffer.concat([describe(q), Flush]) : q.prepare ? q.prepared ? prepared(q) : Buffer.concat([describe(q), prepared(q)]) : unnamed(q);
|
|
704
|
+
}
|
|
705
|
+
function describe(q) {
|
|
706
|
+
return Buffer.concat([
|
|
707
|
+
Parse(q.statement.string, q.parameters, q.statement.types, q.statement.name),
|
|
708
|
+
Describe("S", q.statement.name)
|
|
709
|
+
]);
|
|
710
|
+
}
|
|
711
|
+
function prepared(q) {
|
|
712
|
+
return Buffer.concat([
|
|
713
|
+
Bind(q.parameters, q.statement.types, q.statement.name, q.cursorName),
|
|
714
|
+
q.cursorFn ? Execute("", q.cursorRows) : ExecuteUnnamed
|
|
715
|
+
]);
|
|
716
|
+
}
|
|
717
|
+
function unnamed(q) {
|
|
718
|
+
return Buffer.concat([
|
|
719
|
+
Parse(q.statement.string, q.parameters, q.statement.types),
|
|
720
|
+
DescribeUnnamed,
|
|
721
|
+
prepared(q)
|
|
722
|
+
]);
|
|
723
|
+
}
|
|
724
|
+
function build(q) {
|
|
725
|
+
const parameters = [], types2 = [];
|
|
726
|
+
const string = stringify(q, q.strings[0], q.args[0], parameters, types2, options);
|
|
727
|
+
!q.tagged && q.args.forEach((x) => handleValue(x, parameters, types2, options));
|
|
728
|
+
q.prepare = options.prepare && ("prepare" in q.options ? q.options.prepare : true);
|
|
729
|
+
q.string = string;
|
|
730
|
+
q.signature = q.prepare && types2 + string;
|
|
731
|
+
q.onlyDescribe && delete statements[q.signature];
|
|
732
|
+
q.parameters = q.parameters || parameters;
|
|
733
|
+
q.prepared = q.prepare && q.signature in statements;
|
|
734
|
+
q.describeFirst = q.onlyDescribe || parameters.length && !q.prepared;
|
|
735
|
+
q.statement = q.prepared ? statements[q.signature] : { string, types: types2, name: q.prepare ? statementId + statementCount++ : "" };
|
|
736
|
+
typeof options.debug === "function" && options.debug(id, string, parameters, types2);
|
|
737
|
+
}
|
|
738
|
+
function write(x, fn) {
|
|
739
|
+
chunk = chunk ? Buffer.concat([chunk, x]) : Buffer.from(x);
|
|
740
|
+
if (fn || chunk.length >= 1024)
|
|
741
|
+
return nextWrite(fn);
|
|
742
|
+
nextWriteTimer === null && (nextWriteTimer = setImmediate(nextWrite));
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
function nextWrite(fn) {
|
|
746
|
+
const x = socket.write(chunk, fn);
|
|
747
|
+
nextWriteTimer !== null && clearImmediate(nextWriteTimer);
|
|
748
|
+
chunk = nextWriteTimer = null;
|
|
749
|
+
return x;
|
|
750
|
+
}
|
|
751
|
+
function connectTimedOut() {
|
|
752
|
+
errored(Errors.connection("CONNECT_TIMEOUT", options, socket));
|
|
753
|
+
socket.destroy();
|
|
754
|
+
}
|
|
755
|
+
async function secure() {
|
|
756
|
+
write(SSLRequest);
|
|
757
|
+
const canSSL = await new Promise((r) => socket.once("data", (x) => r(x[0] === 83)));
|
|
758
|
+
if (!canSSL && ssl === "prefer")
|
|
759
|
+
return connected();
|
|
760
|
+
socket.removeAllListeners();
|
|
761
|
+
socket = tls.connect({
|
|
762
|
+
socket,
|
|
763
|
+
servername: net.isIP(socket.host) ? undefined : socket.host,
|
|
764
|
+
...ssl === "require" || ssl === "allow" || ssl === "prefer" ? { rejectUnauthorized: false } : ssl === "verify-full" ? {} : typeof ssl === "object" ? ssl : {}
|
|
765
|
+
});
|
|
766
|
+
socket.on("secureConnect", connected);
|
|
767
|
+
socket.on("error", error);
|
|
768
|
+
socket.on("close", closed);
|
|
769
|
+
socket.on("drain", drain);
|
|
770
|
+
}
|
|
771
|
+
function drain() {
|
|
772
|
+
!query && onopen(connection2);
|
|
773
|
+
}
|
|
774
|
+
function data(x) {
|
|
775
|
+
if (incomings) {
|
|
776
|
+
incomings.push(x);
|
|
777
|
+
remaining -= x.length;
|
|
778
|
+
if (remaining > 0)
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
incoming = incomings ? Buffer.concat(incomings, length - remaining) : incoming.length === 0 ? x : Buffer.concat([incoming, x], incoming.length + x.length);
|
|
782
|
+
while (incoming.length > 4) {
|
|
783
|
+
length = incoming.readUInt32BE(1);
|
|
784
|
+
if (length >= incoming.length) {
|
|
785
|
+
remaining = length - incoming.length;
|
|
786
|
+
incomings = [incoming];
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
try {
|
|
790
|
+
handle(incoming.subarray(0, length + 1));
|
|
791
|
+
} catch (e) {
|
|
792
|
+
query && (query.cursorFn || query.describeFirst) && write(Sync);
|
|
793
|
+
errored(e);
|
|
794
|
+
}
|
|
795
|
+
incoming = incoming.subarray(length + 1);
|
|
796
|
+
remaining = 0;
|
|
797
|
+
incomings = null;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
async function connect() {
|
|
801
|
+
terminated = false;
|
|
802
|
+
backendParameters = {};
|
|
803
|
+
socket || (socket = await createSocket());
|
|
804
|
+
if (!socket)
|
|
805
|
+
return;
|
|
806
|
+
connectTimer.start();
|
|
807
|
+
if (options.socket)
|
|
808
|
+
return ssl ? secure() : connected();
|
|
809
|
+
socket.on("connect", ssl ? secure : connected);
|
|
810
|
+
if (options.path)
|
|
811
|
+
return socket.connect(options.path);
|
|
812
|
+
socket.ssl = ssl;
|
|
813
|
+
socket.connect(port[hostIndex], host[hostIndex]);
|
|
814
|
+
socket.host = host[hostIndex];
|
|
815
|
+
socket.port = port[hostIndex];
|
|
816
|
+
hostIndex = (hostIndex + 1) % port.length;
|
|
817
|
+
}
|
|
818
|
+
function reconnect() {
|
|
819
|
+
setTimeout(connect, closedDate ? closedDate + delay - performance.now() : 0);
|
|
820
|
+
}
|
|
821
|
+
function connected() {
|
|
822
|
+
try {
|
|
823
|
+
statements = {};
|
|
824
|
+
needsTypes = options.fetch_types;
|
|
825
|
+
statementId = Math.random().toString(36).slice(2);
|
|
826
|
+
statementCount = 1;
|
|
827
|
+
lifeTimer.start();
|
|
828
|
+
socket.on("data", data);
|
|
829
|
+
keep_alive && socket.setKeepAlive && socket.setKeepAlive(true, 1000 * keep_alive);
|
|
830
|
+
const s = StartupMessage();
|
|
831
|
+
write(s);
|
|
832
|
+
} catch (err) {
|
|
833
|
+
error(err);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
function error(err) {
|
|
837
|
+
if (connection2.queue === queues.connecting && options.host[retries + 1])
|
|
838
|
+
return;
|
|
839
|
+
errored(err);
|
|
840
|
+
while (sent.length)
|
|
841
|
+
queryError(sent.shift(), err);
|
|
842
|
+
}
|
|
843
|
+
function errored(err) {
|
|
844
|
+
stream && (stream.destroy(err), stream = null);
|
|
845
|
+
query && queryError(query, err);
|
|
846
|
+
initial && (queryError(initial, err), initial = null);
|
|
847
|
+
}
|
|
848
|
+
function queryError(query2, err) {
|
|
849
|
+
if (query2.reserve)
|
|
850
|
+
return query2.reject(err);
|
|
851
|
+
if (!err || typeof err !== "object")
|
|
852
|
+
err = new Error(err);
|
|
853
|
+
"query" in err || "parameters" in err || Object.defineProperties(err, {
|
|
854
|
+
stack: { value: err.stack + query2.origin.replace(/.*\n/, `
|
|
855
|
+
`), enumerable: options.debug },
|
|
856
|
+
query: { value: query2.string, enumerable: options.debug },
|
|
857
|
+
parameters: { value: query2.parameters, enumerable: options.debug },
|
|
858
|
+
args: { value: query2.args, enumerable: options.debug },
|
|
859
|
+
types: { value: query2.statement && query2.statement.types, enumerable: options.debug }
|
|
860
|
+
});
|
|
861
|
+
query2.reject(err);
|
|
862
|
+
}
|
|
863
|
+
function end() {
|
|
864
|
+
return ending || (!connection2.reserved && onend(connection2), !connection2.reserved && !initial && !query && sent.length === 0 ? (terminate(), new Promise((r) => socket && socket.readyState !== "closed" ? socket.once("close", r) : r())) : ending = new Promise((r) => ended = r));
|
|
865
|
+
}
|
|
866
|
+
function terminate() {
|
|
867
|
+
terminated = true;
|
|
868
|
+
if (stream || query || initial || sent.length)
|
|
869
|
+
error(Errors.connection("CONNECTION_DESTROYED", options));
|
|
870
|
+
clearImmediate(nextWriteTimer);
|
|
871
|
+
if (socket) {
|
|
872
|
+
socket.removeListener("data", data);
|
|
873
|
+
socket.removeListener("connect", connected);
|
|
874
|
+
socket.readyState === "open" && socket.end(bytes_default().X().end());
|
|
875
|
+
}
|
|
876
|
+
ended && (ended(), ending = ended = null);
|
|
877
|
+
}
|
|
878
|
+
async function closed(hadError) {
|
|
879
|
+
incoming = Buffer.alloc(0);
|
|
880
|
+
remaining = 0;
|
|
881
|
+
incomings = null;
|
|
882
|
+
clearImmediate(nextWriteTimer);
|
|
883
|
+
socket.removeListener("data", data);
|
|
884
|
+
socket.removeListener("connect", connected);
|
|
885
|
+
idleTimer.cancel();
|
|
886
|
+
lifeTimer.cancel();
|
|
887
|
+
connectTimer.cancel();
|
|
888
|
+
socket.removeAllListeners();
|
|
889
|
+
socket = null;
|
|
890
|
+
if (initial)
|
|
891
|
+
return reconnect();
|
|
892
|
+
!hadError && (query || sent.length) && error(Errors.connection("CONNECTION_CLOSED", options, socket));
|
|
893
|
+
closedDate = performance.now();
|
|
894
|
+
hadError && options.shared.retries++;
|
|
895
|
+
delay = (typeof backoff === "function" ? backoff(options.shared.retries) : backoff) * 1000;
|
|
896
|
+
onclose(connection2, Errors.connection("CONNECTION_CLOSED", options, socket));
|
|
897
|
+
}
|
|
898
|
+
function handle(xs, x = xs[0]) {
|
|
899
|
+
(x === 68 ? DataRow : x === 100 ? CopyData : x === 65 ? NotificationResponse : x === 83 ? ParameterStatus : x === 90 ? ReadyForQuery : x === 67 ? CommandComplete : x === 50 ? BindComplete : x === 49 ? ParseComplete : x === 116 ? ParameterDescription : x === 84 ? RowDescription : x === 82 ? Authentication : x === 110 ? NoData : x === 75 ? BackendKeyData : x === 69 ? ErrorResponse : x === 115 ? PortalSuspended : x === 51 ? CloseComplete : x === 71 ? CopyInResponse : x === 78 ? NoticeResponse : x === 72 ? CopyOutResponse : x === 99 ? CopyDone : x === 73 ? EmptyQueryResponse : x === 86 ? FunctionCallResponse : x === 118 ? NegotiateProtocolVersion : x === 87 ? CopyBothResponse : UnknownMessage)(xs);
|
|
900
|
+
}
|
|
901
|
+
function DataRow(x) {
|
|
902
|
+
let index = 7;
|
|
903
|
+
let length2;
|
|
904
|
+
let column;
|
|
905
|
+
let value;
|
|
906
|
+
const row = query.isRaw ? new Array(query.statement.columns.length) : {};
|
|
907
|
+
for (let i = 0;i < query.statement.columns.length; i++) {
|
|
908
|
+
column = query.statement.columns[i];
|
|
909
|
+
length2 = x.readInt32BE(index);
|
|
910
|
+
index += 4;
|
|
911
|
+
value = length2 === -1 ? null : query.isRaw === true ? x.subarray(index, index += length2) : column.parser === undefined ? x.toString("utf8", index, index += length2) : column.parser.array === true ? column.parser(x.toString("utf8", index + 1, index += length2)) : column.parser(x.toString("utf8", index, index += length2));
|
|
912
|
+
query.isRaw ? row[i] = query.isRaw === true ? value : transform.value.from ? transform.value.from(value, column) : value : row[column.name] = transform.value.from ? transform.value.from(value, column) : value;
|
|
913
|
+
}
|
|
914
|
+
query.forEachFn ? query.forEachFn(transform.row.from ? transform.row.from(row) : row, result) : result[rows++] = transform.row.from ? transform.row.from(row) : row;
|
|
915
|
+
}
|
|
916
|
+
function ParameterStatus(x) {
|
|
917
|
+
const [k, v] = x.toString("utf8", 5, x.length - 1).split(bytes_default.N);
|
|
918
|
+
backendParameters[k] = v;
|
|
919
|
+
if (options.parameters[k] !== v) {
|
|
920
|
+
options.parameters[k] = v;
|
|
921
|
+
onparameter && onparameter(k, v);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
function ReadyForQuery(x) {
|
|
925
|
+
query && query.options.simple && query.resolve(results || result);
|
|
926
|
+
query = results = null;
|
|
927
|
+
result = new Result;
|
|
928
|
+
connectTimer.cancel();
|
|
929
|
+
if (initial) {
|
|
930
|
+
if (target_session_attrs) {
|
|
931
|
+
if (!backendParameters.in_hot_standby || !backendParameters.default_transaction_read_only)
|
|
932
|
+
return fetchState();
|
|
933
|
+
else if (tryNext(target_session_attrs, backendParameters))
|
|
934
|
+
return terminate();
|
|
935
|
+
}
|
|
936
|
+
if (needsTypes) {
|
|
937
|
+
initial.reserve && (initial = null);
|
|
938
|
+
return fetchArrayTypes();
|
|
939
|
+
}
|
|
940
|
+
initial && !initial.reserve && execute(initial);
|
|
941
|
+
options.shared.retries = retries = 0;
|
|
942
|
+
initial = null;
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
while (sent.length && (query = sent.shift()) && (query.active = true, query.cancelled))
|
|
946
|
+
Connection(options).cancel(query.state, query.cancelled.resolve, query.cancelled.reject);
|
|
947
|
+
if (query)
|
|
948
|
+
return;
|
|
949
|
+
connection2.reserved ? !connection2.reserved.release && x[5] === 73 ? ending ? terminate() : (connection2.reserved = null, onopen(connection2)) : connection2.reserved() : ending ? terminate() : onopen(connection2);
|
|
950
|
+
}
|
|
951
|
+
function CommandComplete(x) {
|
|
952
|
+
rows = 0;
|
|
953
|
+
for (let i = x.length - 1;i > 0; i--) {
|
|
954
|
+
if (x[i] === 32 && x[i + 1] < 58 && result.count === null)
|
|
955
|
+
result.count = +x.toString("utf8", i + 1, x.length - 1);
|
|
956
|
+
if (x[i - 1] >= 65) {
|
|
957
|
+
result.command = x.toString("utf8", 5, i);
|
|
958
|
+
result.state = backend;
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
final && (final(), final = null);
|
|
963
|
+
if (result.command === "BEGIN" && max !== 1 && !connection2.reserved)
|
|
964
|
+
return errored(Errors.generic("UNSAFE_TRANSACTION", "Only use sql.begin, sql.reserved or max: 1"));
|
|
965
|
+
if (query.options.simple)
|
|
966
|
+
return BindComplete();
|
|
967
|
+
if (query.cursorFn) {
|
|
968
|
+
result.count && query.cursorFn(result);
|
|
969
|
+
write(Sync);
|
|
970
|
+
}
|
|
971
|
+
query.resolve(result);
|
|
972
|
+
}
|
|
973
|
+
function ParseComplete() {
|
|
974
|
+
query.parsing = false;
|
|
975
|
+
}
|
|
976
|
+
function BindComplete() {
|
|
977
|
+
!result.statement && (result.statement = query.statement);
|
|
978
|
+
result.columns = query.statement.columns;
|
|
979
|
+
}
|
|
980
|
+
function ParameterDescription(x) {
|
|
981
|
+
const length2 = x.readUInt16BE(5);
|
|
982
|
+
for (let i = 0;i < length2; ++i)
|
|
983
|
+
!query.statement.types[i] && (query.statement.types[i] = x.readUInt32BE(7 + i * 4));
|
|
984
|
+
query.prepare && (statements[query.signature] = query.statement);
|
|
985
|
+
query.describeFirst && !query.onlyDescribe && (write(prepared(query)), query.describeFirst = false);
|
|
986
|
+
}
|
|
987
|
+
function RowDescription(x) {
|
|
988
|
+
if (result.command) {
|
|
989
|
+
results = results || [result];
|
|
990
|
+
results.push(result = new Result);
|
|
991
|
+
result.count = null;
|
|
992
|
+
query.statement.columns = null;
|
|
993
|
+
}
|
|
994
|
+
const length2 = x.readUInt16BE(5);
|
|
995
|
+
let index = 7;
|
|
996
|
+
let start;
|
|
997
|
+
query.statement.columns = Array(length2);
|
|
998
|
+
for (let i = 0;i < length2; ++i) {
|
|
999
|
+
start = index;
|
|
1000
|
+
while (x[index++] !== 0)
|
|
1001
|
+
;
|
|
1002
|
+
const table = x.readUInt32BE(index);
|
|
1003
|
+
const number = x.readUInt16BE(index + 4);
|
|
1004
|
+
const type = x.readUInt32BE(index + 6);
|
|
1005
|
+
query.statement.columns[i] = {
|
|
1006
|
+
name: transform.column.from ? transform.column.from(x.toString("utf8", start, index - 1)) : x.toString("utf8", start, index - 1),
|
|
1007
|
+
parser: parsers2[type],
|
|
1008
|
+
table,
|
|
1009
|
+
number,
|
|
1010
|
+
type
|
|
1011
|
+
};
|
|
1012
|
+
index += 18;
|
|
1013
|
+
}
|
|
1014
|
+
result.statement = query.statement;
|
|
1015
|
+
if (query.onlyDescribe)
|
|
1016
|
+
return query.resolve(query.statement), write(Sync);
|
|
1017
|
+
}
|
|
1018
|
+
async function Authentication(x, type = x.readUInt32BE(5)) {
|
|
1019
|
+
(type === 3 ? AuthenticationCleartextPassword : type === 5 ? AuthenticationMD5Password : type === 10 ? SASL : type === 11 ? SASLContinue : type === 12 ? SASLFinal : type !== 0 ? UnknownAuth : noop)(x, type);
|
|
1020
|
+
}
|
|
1021
|
+
async function AuthenticationCleartextPassword() {
|
|
1022
|
+
const payload = await Pass();
|
|
1023
|
+
write(bytes_default().p().str(payload).z(1).end());
|
|
1024
|
+
}
|
|
1025
|
+
async function AuthenticationMD5Password(x) {
|
|
1026
|
+
const payload = "md5" + await md5(Buffer.concat([
|
|
1027
|
+
Buffer.from(await md5(await Pass() + user)),
|
|
1028
|
+
x.subarray(9)
|
|
1029
|
+
]));
|
|
1030
|
+
write(bytes_default().p().str(payload).z(1).end());
|
|
1031
|
+
}
|
|
1032
|
+
async function SASL() {
|
|
1033
|
+
nonce = (await crypto.randomBytes(18)).toString("base64");
|
|
1034
|
+
bytes_default().p().str("SCRAM-SHA-256" + bytes_default.N);
|
|
1035
|
+
const i = bytes_default.i;
|
|
1036
|
+
write(bytes_default.inc(4).str("n,,n=*,r=" + nonce).i32(bytes_default.i - i - 4, i).end());
|
|
1037
|
+
}
|
|
1038
|
+
async function SASLContinue(x) {
|
|
1039
|
+
const res = x.toString("utf8", 9).split(",").reduce((acc, x2) => (acc[x2[0]] = x2.slice(2), acc), {});
|
|
1040
|
+
const saltedPassword = await crypto.pbkdf2Sync(await Pass(), Buffer.from(res.s, "base64"), parseInt(res.i), 32, "sha256");
|
|
1041
|
+
const clientKey = await hmac(saltedPassword, "Client Key");
|
|
1042
|
+
const auth = "n=*,r=" + nonce + "," + "r=" + res.r + ",s=" + res.s + ",i=" + res.i + ",c=biws,r=" + res.r;
|
|
1043
|
+
serverSignature = (await hmac(await hmac(saltedPassword, "Server Key"), auth)).toString("base64");
|
|
1044
|
+
const payload = "c=biws,r=" + res.r + ",p=" + xor(clientKey, Buffer.from(await hmac(await sha256(clientKey), auth))).toString("base64");
|
|
1045
|
+
write(bytes_default().p().str(payload).end());
|
|
1046
|
+
}
|
|
1047
|
+
function SASLFinal(x) {
|
|
1048
|
+
if (x.toString("utf8", 9).split(bytes_default.N, 1)[0].slice(2) === serverSignature)
|
|
1049
|
+
return;
|
|
1050
|
+
errored(Errors.generic("SASL_SIGNATURE_MISMATCH", "The server did not return the correct signature"));
|
|
1051
|
+
socket.destroy();
|
|
1052
|
+
}
|
|
1053
|
+
function Pass() {
|
|
1054
|
+
return Promise.resolve(typeof options.pass === "function" ? options.pass() : options.pass);
|
|
1055
|
+
}
|
|
1056
|
+
function NoData() {
|
|
1057
|
+
result.statement = query.statement;
|
|
1058
|
+
result.statement.columns = [];
|
|
1059
|
+
if (query.onlyDescribe)
|
|
1060
|
+
return query.resolve(query.statement), write(Sync);
|
|
1061
|
+
}
|
|
1062
|
+
function BackendKeyData(x) {
|
|
1063
|
+
backend.pid = x.readUInt32BE(5);
|
|
1064
|
+
backend.secret = x.readUInt32BE(9);
|
|
1065
|
+
}
|
|
1066
|
+
async function fetchArrayTypes() {
|
|
1067
|
+
needsTypes = false;
|
|
1068
|
+
const types2 = await new Query([`
|
|
1069
|
+
select b.oid, b.typarray
|
|
1070
|
+
from pg_catalog.pg_type a
|
|
1071
|
+
left join pg_catalog.pg_type b on b.oid = a.typelem
|
|
1072
|
+
where a.typcategory = 'A'
|
|
1073
|
+
group by b.oid, b.typarray
|
|
1074
|
+
order by b.oid
|
|
1075
|
+
`], [], execute);
|
|
1076
|
+
types2.forEach(({ oid, typarray }) => addArrayType(oid, typarray));
|
|
1077
|
+
}
|
|
1078
|
+
function addArrayType(oid, typarray) {
|
|
1079
|
+
if (!!options.parsers[typarray] && !!options.serializers[typarray])
|
|
1080
|
+
return;
|
|
1081
|
+
const parser = options.parsers[oid];
|
|
1082
|
+
options.shared.typeArrayMap[oid] = typarray;
|
|
1083
|
+
options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray);
|
|
1084
|
+
options.parsers[typarray].array = true;
|
|
1085
|
+
options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options, typarray);
|
|
1086
|
+
}
|
|
1087
|
+
function tryNext(x, xs) {
|
|
1088
|
+
return x === "read-write" && xs.default_transaction_read_only === "on" || x === "read-only" && xs.default_transaction_read_only === "off" || x === "primary" && xs.in_hot_standby === "on" || x === "standby" && xs.in_hot_standby === "off" || x === "prefer-standby" && xs.in_hot_standby === "off" && options.host[retries];
|
|
1089
|
+
}
|
|
1090
|
+
function fetchState() {
|
|
1091
|
+
const query2 = new Query([`
|
|
1092
|
+
show transaction_read_only;
|
|
1093
|
+
select pg_catalog.pg_is_in_recovery()
|
|
1094
|
+
`], [], execute, null, { simple: true });
|
|
1095
|
+
query2.resolve = ([[a], [b2]]) => {
|
|
1096
|
+
backendParameters.default_transaction_read_only = a.transaction_read_only;
|
|
1097
|
+
backendParameters.in_hot_standby = b2.pg_is_in_recovery ? "on" : "off";
|
|
1098
|
+
};
|
|
1099
|
+
query2.execute();
|
|
1100
|
+
}
|
|
1101
|
+
function ErrorResponse(x) {
|
|
1102
|
+
query && (query.cursorFn || query.describeFirst) && write(Sync);
|
|
1103
|
+
const error2 = Errors.postgres(parseError(x));
|
|
1104
|
+
query && query.retried ? errored(query.retried) : query && query.prepared && retryRoutines.has(error2.routine) ? retry(query, error2) : errored(error2);
|
|
1105
|
+
}
|
|
1106
|
+
function retry(q, error2) {
|
|
1107
|
+
delete statements[q.signature];
|
|
1108
|
+
q.retried = error2;
|
|
1109
|
+
execute(q);
|
|
1110
|
+
}
|
|
1111
|
+
function NotificationResponse(x) {
|
|
1112
|
+
if (!onnotify)
|
|
1113
|
+
return;
|
|
1114
|
+
let index = 9;
|
|
1115
|
+
while (x[index++] !== 0)
|
|
1116
|
+
;
|
|
1117
|
+
onnotify(x.toString("utf8", 9, index - 1), x.toString("utf8", index, x.length - 1));
|
|
1118
|
+
}
|
|
1119
|
+
async function PortalSuspended() {
|
|
1120
|
+
try {
|
|
1121
|
+
const x = await Promise.resolve(query.cursorFn(result));
|
|
1122
|
+
rows = 0;
|
|
1123
|
+
x === CLOSE ? write(Close(query.portal)) : (result = new Result, write(Execute("", query.cursorRows)));
|
|
1124
|
+
} catch (err) {
|
|
1125
|
+
write(Sync);
|
|
1126
|
+
query.reject(err);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
function CloseComplete() {
|
|
1130
|
+
result.count && query.cursorFn(result);
|
|
1131
|
+
query.resolve(result);
|
|
1132
|
+
}
|
|
1133
|
+
function CopyInResponse() {
|
|
1134
|
+
stream = new Stream.Writable({
|
|
1135
|
+
autoDestroy: true,
|
|
1136
|
+
write(chunk2, encoding, callback) {
|
|
1137
|
+
socket.write(bytes_default().d().raw(chunk2).end(), callback);
|
|
1138
|
+
},
|
|
1139
|
+
destroy(error2, callback) {
|
|
1140
|
+
callback(error2);
|
|
1141
|
+
socket.write(bytes_default().f().str(error2 + bytes_default.N).end());
|
|
1142
|
+
stream = null;
|
|
1143
|
+
},
|
|
1144
|
+
final(callback) {
|
|
1145
|
+
socket.write(bytes_default().c().end());
|
|
1146
|
+
final = callback;
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
query.resolve(stream);
|
|
1150
|
+
}
|
|
1151
|
+
function CopyOutResponse() {
|
|
1152
|
+
stream = new Stream.Readable({
|
|
1153
|
+
read() {
|
|
1154
|
+
socket.resume();
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
query.resolve(stream);
|
|
1158
|
+
}
|
|
1159
|
+
function CopyBothResponse() {
|
|
1160
|
+
stream = new Stream.Duplex({
|
|
1161
|
+
autoDestroy: true,
|
|
1162
|
+
read() {
|
|
1163
|
+
socket.resume();
|
|
1164
|
+
},
|
|
1165
|
+
write(chunk2, encoding, callback) {
|
|
1166
|
+
socket.write(bytes_default().d().raw(chunk2).end(), callback);
|
|
1167
|
+
},
|
|
1168
|
+
destroy(error2, callback) {
|
|
1169
|
+
callback(error2);
|
|
1170
|
+
socket.write(bytes_default().f().str(error2 + bytes_default.N).end());
|
|
1171
|
+
stream = null;
|
|
1172
|
+
},
|
|
1173
|
+
final(callback) {
|
|
1174
|
+
socket.write(bytes_default().c().end());
|
|
1175
|
+
final = callback;
|
|
1176
|
+
}
|
|
1177
|
+
});
|
|
1178
|
+
query.resolve(stream);
|
|
1179
|
+
}
|
|
1180
|
+
function CopyData(x) {
|
|
1181
|
+
stream && (stream.push(x.subarray(5)) || socket.pause());
|
|
1182
|
+
}
|
|
1183
|
+
function CopyDone() {
|
|
1184
|
+
stream && stream.push(null);
|
|
1185
|
+
stream = null;
|
|
1186
|
+
}
|
|
1187
|
+
function NoticeResponse(x) {
|
|
1188
|
+
onnotice ? onnotice(parseError(x)) : console.log(parseError(x));
|
|
1189
|
+
}
|
|
1190
|
+
function EmptyQueryResponse() {}
|
|
1191
|
+
function FunctionCallResponse() {
|
|
1192
|
+
errored(Errors.notSupported("FunctionCallResponse"));
|
|
1193
|
+
}
|
|
1194
|
+
function NegotiateProtocolVersion() {
|
|
1195
|
+
errored(Errors.notSupported("NegotiateProtocolVersion"));
|
|
1196
|
+
}
|
|
1197
|
+
function UnknownMessage(x) {
|
|
1198
|
+
console.error("Postgres.js : Unknown Message:", x[0]);
|
|
1199
|
+
}
|
|
1200
|
+
function UnknownAuth(x, type) {
|
|
1201
|
+
console.error("Postgres.js : Unknown Auth:", type);
|
|
1202
|
+
}
|
|
1203
|
+
function Bind(parameters, types2, statement = "", portal = "") {
|
|
1204
|
+
let prev, type;
|
|
1205
|
+
bytes_default().B().str(portal + bytes_default.N).str(statement + bytes_default.N).i16(0).i16(parameters.length);
|
|
1206
|
+
parameters.forEach((x, i) => {
|
|
1207
|
+
if (x === null)
|
|
1208
|
+
return bytes_default.i32(4294967295);
|
|
1209
|
+
type = types2[i];
|
|
1210
|
+
parameters[i] = x = type in options.serializers ? options.serializers[type](x) : "" + x;
|
|
1211
|
+
prev = bytes_default.i;
|
|
1212
|
+
bytes_default.inc(4).str(x).i32(bytes_default.i - prev - 4, prev);
|
|
1213
|
+
});
|
|
1214
|
+
bytes_default.i16(0);
|
|
1215
|
+
return bytes_default.end();
|
|
1216
|
+
}
|
|
1217
|
+
function Parse(str, parameters, types2, name = "") {
|
|
1218
|
+
bytes_default().P().str(name + bytes_default.N).str(str + bytes_default.N).i16(parameters.length);
|
|
1219
|
+
parameters.forEach((x, i) => bytes_default.i32(types2[i] || 0));
|
|
1220
|
+
return bytes_default.end();
|
|
1221
|
+
}
|
|
1222
|
+
function Describe(x, name = "") {
|
|
1223
|
+
return bytes_default().D().str(x).str(name + bytes_default.N).end();
|
|
1224
|
+
}
|
|
1225
|
+
function Execute(portal = "", rows2 = 0) {
|
|
1226
|
+
return Buffer.concat([
|
|
1227
|
+
bytes_default().E().str(portal + bytes_default.N).i32(rows2).end(),
|
|
1228
|
+
Flush
|
|
1229
|
+
]);
|
|
1230
|
+
}
|
|
1231
|
+
function Close(portal = "") {
|
|
1232
|
+
return Buffer.concat([
|
|
1233
|
+
bytes_default().C().str("P").str(portal + bytes_default.N).end(),
|
|
1234
|
+
bytes_default().S().end()
|
|
1235
|
+
]);
|
|
1236
|
+
}
|
|
1237
|
+
function StartupMessage() {
|
|
1238
|
+
return cancelMessage || bytes_default().inc(4).i16(3).z(2).str(Object.entries(Object.assign({
|
|
1239
|
+
user,
|
|
1240
|
+
database,
|
|
1241
|
+
client_encoding: "UTF8"
|
|
1242
|
+
}, options.connection)).filter(([, v]) => v).map(([k, v]) => k + bytes_default.N + v).join(bytes_default.N)).z(2).end(0);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
function parseError(x) {
|
|
1246
|
+
const error = {};
|
|
1247
|
+
let start = 5;
|
|
1248
|
+
for (let i = 5;i < x.length - 1; i++) {
|
|
1249
|
+
if (x[i] === 0) {
|
|
1250
|
+
error[errorFields[x[start]]] = x.toString("utf8", start + 1, i);
|
|
1251
|
+
start = i + 1;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
return error;
|
|
1255
|
+
}
|
|
1256
|
+
function md5(x) {
|
|
1257
|
+
return crypto.createHash("md5").update(x).digest("hex");
|
|
1258
|
+
}
|
|
1259
|
+
function hmac(key, x) {
|
|
1260
|
+
return crypto.createHmac("sha256", key).update(x).digest();
|
|
1261
|
+
}
|
|
1262
|
+
function sha256(x) {
|
|
1263
|
+
return crypto.createHash("sha256").update(x).digest();
|
|
1264
|
+
}
|
|
1265
|
+
function xor(a, b2) {
|
|
1266
|
+
const length = Math.max(a.length, b2.length);
|
|
1267
|
+
const buffer2 = Buffer.allocUnsafe(length);
|
|
1268
|
+
for (let i = 0;i < length; i++)
|
|
1269
|
+
buffer2[i] = a[i] ^ b2[i];
|
|
1270
|
+
return buffer2;
|
|
1271
|
+
}
|
|
1272
|
+
function timer(fn, seconds) {
|
|
1273
|
+
seconds = typeof seconds === "function" ? seconds() : seconds;
|
|
1274
|
+
if (!seconds)
|
|
1275
|
+
return { cancel: noop, start: noop };
|
|
1276
|
+
let timer2;
|
|
1277
|
+
return {
|
|
1278
|
+
cancel() {
|
|
1279
|
+
timer2 && (clearTimeout(timer2), timer2 = null);
|
|
1280
|
+
},
|
|
1281
|
+
start() {
|
|
1282
|
+
timer2 && clearTimeout(timer2);
|
|
1283
|
+
timer2 = setTimeout(done, seconds * 1000, arguments);
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
function done(args) {
|
|
1287
|
+
fn.apply(null, args);
|
|
1288
|
+
timer2 = null;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// node_modules/postgres/src/subscribe.js
|
|
1293
|
+
var noop2 = () => {};
|
|
1294
|
+
function Subscribe(postgres2, options) {
|
|
1295
|
+
const subscribers = new Map, slot = "postgresjs_" + Math.random().toString(36).slice(2), state = {};
|
|
1296
|
+
let connection2, stream, ended = false;
|
|
1297
|
+
const sql = subscribe.sql = postgres2({
|
|
1298
|
+
...options,
|
|
1299
|
+
transform: { column: {}, value: {}, row: {} },
|
|
1300
|
+
max: 1,
|
|
1301
|
+
fetch_types: false,
|
|
1302
|
+
idle_timeout: null,
|
|
1303
|
+
max_lifetime: null,
|
|
1304
|
+
connection: {
|
|
1305
|
+
...options.connection,
|
|
1306
|
+
replication: "database"
|
|
1307
|
+
},
|
|
1308
|
+
onclose: async function() {
|
|
1309
|
+
if (ended)
|
|
1310
|
+
return;
|
|
1311
|
+
stream = null;
|
|
1312
|
+
state.pid = state.secret = undefined;
|
|
1313
|
+
connected(await init(sql, slot, options.publications));
|
|
1314
|
+
subscribers.forEach((event) => event.forEach(({ onsubscribe }) => onsubscribe()));
|
|
1315
|
+
},
|
|
1316
|
+
no_subscribe: true
|
|
1317
|
+
});
|
|
1318
|
+
const { end, close } = sql;
|
|
1319
|
+
sql.end = async () => {
|
|
1320
|
+
ended = true;
|
|
1321
|
+
stream && await new Promise((r) => (stream.once("close", r), stream.end()));
|
|
1322
|
+
return end();
|
|
1323
|
+
};
|
|
1324
|
+
sql.close = async () => {
|
|
1325
|
+
stream && await new Promise((r) => (stream.once("close", r), stream.end()));
|
|
1326
|
+
return close();
|
|
1327
|
+
};
|
|
1328
|
+
return subscribe;
|
|
1329
|
+
async function subscribe(event, fn, onsubscribe = noop2, onerror = noop2) {
|
|
1330
|
+
event = parseEvent(event);
|
|
1331
|
+
if (!connection2)
|
|
1332
|
+
connection2 = init(sql, slot, options.publications);
|
|
1333
|
+
const subscriber = { fn, onsubscribe };
|
|
1334
|
+
const fns = subscribers.has(event) ? subscribers.get(event).add(subscriber) : subscribers.set(event, new Set([subscriber])).get(event);
|
|
1335
|
+
const unsubscribe = () => {
|
|
1336
|
+
fns.delete(subscriber);
|
|
1337
|
+
fns.size === 0 && subscribers.delete(event);
|
|
1338
|
+
};
|
|
1339
|
+
return connection2.then((x) => {
|
|
1340
|
+
connected(x);
|
|
1341
|
+
onsubscribe();
|
|
1342
|
+
stream && stream.on("error", onerror);
|
|
1343
|
+
return { unsubscribe, state, sql };
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
function connected(x) {
|
|
1347
|
+
stream = x.stream;
|
|
1348
|
+
state.pid = x.state.pid;
|
|
1349
|
+
state.secret = x.state.secret;
|
|
1350
|
+
}
|
|
1351
|
+
async function init(sql2, slot2, publications) {
|
|
1352
|
+
if (!publications)
|
|
1353
|
+
throw new Error("Missing publication names");
|
|
1354
|
+
const xs = await sql2.unsafe(`CREATE_REPLICATION_SLOT ${slot2} TEMPORARY LOGICAL pgoutput NOEXPORT_SNAPSHOT`);
|
|
1355
|
+
const [x] = xs;
|
|
1356
|
+
const stream2 = await sql2.unsafe(`START_REPLICATION SLOT ${slot2} LOGICAL ${x.consistent_point} (proto_version '1', publication_names '${publications}')`).writable();
|
|
1357
|
+
const state2 = {
|
|
1358
|
+
lsn: Buffer.concat(x.consistent_point.split("/").map((x2) => Buffer.from(("00000000" + x2).slice(-8), "hex")))
|
|
1359
|
+
};
|
|
1360
|
+
stream2.on("data", data);
|
|
1361
|
+
stream2.on("error", error);
|
|
1362
|
+
stream2.on("close", sql2.close);
|
|
1363
|
+
return { stream: stream2, state: xs.state };
|
|
1364
|
+
function error(e) {
|
|
1365
|
+
console.error("Unexpected error during logical streaming - reconnecting", e);
|
|
1366
|
+
}
|
|
1367
|
+
function data(x2) {
|
|
1368
|
+
if (x2[0] === 119) {
|
|
1369
|
+
parse(x2.subarray(25), state2, sql2.options.parsers, handle, options.transform);
|
|
1370
|
+
} else if (x2[0] === 107 && x2[17]) {
|
|
1371
|
+
state2.lsn = x2.subarray(1, 9);
|
|
1372
|
+
pong();
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
function handle(a, b2) {
|
|
1376
|
+
const path = b2.relation.schema + "." + b2.relation.table;
|
|
1377
|
+
call("*", a, b2);
|
|
1378
|
+
call("*:" + path, a, b2);
|
|
1379
|
+
b2.relation.keys.length && call("*:" + path + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2);
|
|
1380
|
+
call(b2.command, a, b2);
|
|
1381
|
+
call(b2.command + ":" + path, a, b2);
|
|
1382
|
+
b2.relation.keys.length && call(b2.command + ":" + path + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2);
|
|
1383
|
+
}
|
|
1384
|
+
function pong() {
|
|
1385
|
+
const x2 = Buffer.alloc(34);
|
|
1386
|
+
x2[0] = 114;
|
|
1387
|
+
x2.fill(state2.lsn, 1);
|
|
1388
|
+
x2.writeBigInt64BE(BigInt(Date.now() - Date.UTC(2000, 0, 1)) * BigInt(1000), 25);
|
|
1389
|
+
stream2.write(x2);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
function call(x, a, b2) {
|
|
1393
|
+
subscribers.has(x) && subscribers.get(x).forEach(({ fn }) => fn(a, b2, x));
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
function Time(x) {
|
|
1397
|
+
return new Date(Date.UTC(2000, 0, 1) + Number(x / BigInt(1000)));
|
|
1398
|
+
}
|
|
1399
|
+
function parse(x, state, parsers2, handle, transform) {
|
|
1400
|
+
const char = (acc, [k, v]) => (acc[k.charCodeAt(0)] = v, acc);
|
|
1401
|
+
Object.entries({
|
|
1402
|
+
R: (x2) => {
|
|
1403
|
+
let i = 1;
|
|
1404
|
+
const r = state[x2.readUInt32BE(i)] = {
|
|
1405
|
+
schema: x2.toString("utf8", i += 4, i = x2.indexOf(0, i)) || "pg_catalog",
|
|
1406
|
+
table: x2.toString("utf8", i + 1, i = x2.indexOf(0, i + 1)),
|
|
1407
|
+
columns: Array(x2.readUInt16BE(i += 2)),
|
|
1408
|
+
keys: []
|
|
1409
|
+
};
|
|
1410
|
+
i += 2;
|
|
1411
|
+
let columnIndex = 0, column;
|
|
1412
|
+
while (i < x2.length) {
|
|
1413
|
+
column = r.columns[columnIndex++] = {
|
|
1414
|
+
key: x2[i++],
|
|
1415
|
+
name: transform.column.from ? transform.column.from(x2.toString("utf8", i, i = x2.indexOf(0, i))) : x2.toString("utf8", i, i = x2.indexOf(0, i)),
|
|
1416
|
+
type: x2.readUInt32BE(i += 1),
|
|
1417
|
+
parser: parsers2[x2.readUInt32BE(i)],
|
|
1418
|
+
atttypmod: x2.readUInt32BE(i += 4)
|
|
1419
|
+
};
|
|
1420
|
+
column.key && r.keys.push(column);
|
|
1421
|
+
i += 4;
|
|
1422
|
+
}
|
|
1423
|
+
},
|
|
1424
|
+
Y: () => {},
|
|
1425
|
+
O: () => {},
|
|
1426
|
+
B: (x2) => {
|
|
1427
|
+
state.date = Time(x2.readBigInt64BE(9));
|
|
1428
|
+
state.lsn = x2.subarray(1, 9);
|
|
1429
|
+
},
|
|
1430
|
+
I: (x2) => {
|
|
1431
|
+
let i = 1;
|
|
1432
|
+
const relation = state[x2.readUInt32BE(i)];
|
|
1433
|
+
const { row } = tuples(x2, relation.columns, i += 7, transform);
|
|
1434
|
+
handle(row, {
|
|
1435
|
+
command: "insert",
|
|
1436
|
+
relation
|
|
1437
|
+
});
|
|
1438
|
+
},
|
|
1439
|
+
D: (x2) => {
|
|
1440
|
+
let i = 1;
|
|
1441
|
+
const relation = state[x2.readUInt32BE(i)];
|
|
1442
|
+
i += 4;
|
|
1443
|
+
const key = x2[i] === 75;
|
|
1444
|
+
handle(key || x2[i] === 79 ? tuples(x2, relation.columns, i += 3, transform).row : null, {
|
|
1445
|
+
command: "delete",
|
|
1446
|
+
relation,
|
|
1447
|
+
key
|
|
1448
|
+
});
|
|
1449
|
+
},
|
|
1450
|
+
U: (x2) => {
|
|
1451
|
+
let i = 1;
|
|
1452
|
+
const relation = state[x2.readUInt32BE(i)];
|
|
1453
|
+
i += 4;
|
|
1454
|
+
const key = x2[i] === 75;
|
|
1455
|
+
const xs = key || x2[i] === 79 ? tuples(x2, relation.columns, i += 3, transform) : null;
|
|
1456
|
+
xs && (i = xs.i);
|
|
1457
|
+
const { row } = tuples(x2, relation.columns, i + 3, transform);
|
|
1458
|
+
handle(row, {
|
|
1459
|
+
command: "update",
|
|
1460
|
+
relation,
|
|
1461
|
+
key,
|
|
1462
|
+
old: xs && xs.row
|
|
1463
|
+
});
|
|
1464
|
+
},
|
|
1465
|
+
T: () => {},
|
|
1466
|
+
C: () => {}
|
|
1467
|
+
}).reduce(char, {})[x[0]](x);
|
|
1468
|
+
}
|
|
1469
|
+
function tuples(x, columns, xi, transform) {
|
|
1470
|
+
let type, column, value;
|
|
1471
|
+
const row = transform.raw ? new Array(columns.length) : {};
|
|
1472
|
+
for (let i = 0;i < columns.length; i++) {
|
|
1473
|
+
type = x[xi++];
|
|
1474
|
+
column = columns[i];
|
|
1475
|
+
value = type === 110 ? null : type === 117 ? undefined : column.parser === undefined ? x.toString("utf8", xi + 4, xi += 4 + x.readUInt32BE(xi)) : column.parser.array === true ? column.parser(x.toString("utf8", xi + 5, xi += 4 + x.readUInt32BE(xi))) : column.parser(x.toString("utf8", xi + 4, xi += 4 + x.readUInt32BE(xi)));
|
|
1476
|
+
transform.raw ? row[i] = transform.raw === true ? value : transform.value.from ? transform.value.from(value, column) : value : row[column.name] = transform.value.from ? transform.value.from(value, column) : value;
|
|
1477
|
+
}
|
|
1478
|
+
return { i: xi, row: transform.row.from ? transform.row.from(row) : row };
|
|
1479
|
+
}
|
|
1480
|
+
function parseEvent(x) {
|
|
1481
|
+
const xs = x.match(/^(\*|insert|update|delete)?:?([^.]+?\.?[^=]+)?=?(.+)?/i) || [];
|
|
1482
|
+
if (!xs)
|
|
1483
|
+
throw new Error("Malformed subscribe pattern: " + x);
|
|
1484
|
+
const [, command, path, key] = xs;
|
|
1485
|
+
return (command || "*") + (path ? ":" + (path.indexOf(".") === -1 ? "public." + path : path) : "") + (key ? "=" + key : "");
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
// node_modules/postgres/src/large.js
|
|
1489
|
+
import Stream2 from "stream";
|
|
1490
|
+
function largeObject(sql, oid, mode = 131072 | 262144) {
|
|
1491
|
+
return new Promise(async (resolve, reject) => {
|
|
1492
|
+
await sql.begin(async (sql2) => {
|
|
1493
|
+
let finish;
|
|
1494
|
+
!oid && ([{ oid }] = await sql2`select lo_creat(-1) as oid`);
|
|
1495
|
+
const [{ fd }] = await sql2`select lo_open(${oid}, ${mode}) as fd`;
|
|
1496
|
+
const lo = {
|
|
1497
|
+
writable,
|
|
1498
|
+
readable,
|
|
1499
|
+
close: () => sql2`select lo_close(${fd})`.then(finish),
|
|
1500
|
+
tell: () => sql2`select lo_tell64(${fd})`,
|
|
1501
|
+
read: (x) => sql2`select loread(${fd}, ${x}) as data`,
|
|
1502
|
+
write: (x) => sql2`select lowrite(${fd}, ${x})`,
|
|
1503
|
+
truncate: (x) => sql2`select lo_truncate64(${fd}, ${x})`,
|
|
1504
|
+
seek: (x, whence = 0) => sql2`select lo_lseek64(${fd}, ${x}, ${whence})`,
|
|
1505
|
+
size: () => sql2`
|
|
1506
|
+
select
|
|
1507
|
+
lo_lseek64(${fd}, location, 0) as position,
|
|
1508
|
+
seek.size
|
|
1509
|
+
from (
|
|
1510
|
+
select
|
|
1511
|
+
lo_lseek64($1, 0, 2) as size,
|
|
1512
|
+
tell.location
|
|
1513
|
+
from (select lo_tell64($1) as location) tell
|
|
1514
|
+
) seek
|
|
1515
|
+
`
|
|
1516
|
+
};
|
|
1517
|
+
resolve(lo);
|
|
1518
|
+
return new Promise(async (r) => finish = r);
|
|
1519
|
+
async function readable({
|
|
1520
|
+
highWaterMark = 2048 * 8,
|
|
1521
|
+
start = 0,
|
|
1522
|
+
end = Infinity
|
|
1523
|
+
} = {}) {
|
|
1524
|
+
let max = end - start;
|
|
1525
|
+
start && await lo.seek(start);
|
|
1526
|
+
return new Stream2.Readable({
|
|
1527
|
+
highWaterMark,
|
|
1528
|
+
async read(size2) {
|
|
1529
|
+
const l = size2 > max ? size2 - max : size2;
|
|
1530
|
+
max -= size2;
|
|
1531
|
+
const [{ data }] = await lo.read(l);
|
|
1532
|
+
this.push(data);
|
|
1533
|
+
if (data.length < size2)
|
|
1534
|
+
this.push(null);
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
async function writable({
|
|
1539
|
+
highWaterMark = 2048 * 8,
|
|
1540
|
+
start = 0
|
|
1541
|
+
} = {}) {
|
|
1542
|
+
start && await lo.seek(start);
|
|
1543
|
+
return new Stream2.Writable({
|
|
1544
|
+
highWaterMark,
|
|
1545
|
+
write(chunk, encoding, callback) {
|
|
1546
|
+
lo.write(chunk).then(() => callback(), callback);
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
}).catch(reject);
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
// node_modules/postgres/src/index.js
|
|
1555
|
+
Object.assign(Postgres, {
|
|
1556
|
+
PostgresError,
|
|
1557
|
+
toPascal,
|
|
1558
|
+
pascal,
|
|
1559
|
+
toCamel,
|
|
1560
|
+
camel,
|
|
1561
|
+
toKebab,
|
|
1562
|
+
kebab,
|
|
1563
|
+
fromPascal,
|
|
1564
|
+
fromCamel,
|
|
1565
|
+
fromKebab,
|
|
1566
|
+
BigInt: {
|
|
1567
|
+
to: 20,
|
|
1568
|
+
from: [20],
|
|
1569
|
+
parse: (x) => BigInt(x),
|
|
1570
|
+
serialize: (x) => x.toString()
|
|
1571
|
+
}
|
|
1572
|
+
});
|
|
1573
|
+
var src_default = Postgres;
|
|
1574
|
+
function Postgres(a, b2) {
|
|
1575
|
+
const options = parseOptions(a, b2), subscribe = options.no_subscribe || Subscribe(Postgres, { ...options });
|
|
1576
|
+
let ending = false;
|
|
1577
|
+
const queries = queue_default(), connecting = queue_default(), reserved = queue_default(), closed = queue_default(), ended = queue_default(), open = queue_default(), busy = queue_default(), full = queue_default(), queues = { connecting, reserved, closed, ended, open, busy, full };
|
|
1578
|
+
const connections = [...Array(options.max)].map(() => connection_default(options, queues, { onopen, onend, onclose }));
|
|
1579
|
+
const sql = Sql(handler);
|
|
1580
|
+
Object.assign(sql, {
|
|
1581
|
+
get parameters() {
|
|
1582
|
+
return options.parameters;
|
|
1583
|
+
},
|
|
1584
|
+
largeObject: largeObject.bind(null, sql),
|
|
1585
|
+
subscribe,
|
|
1586
|
+
CLOSE,
|
|
1587
|
+
END: CLOSE,
|
|
1588
|
+
PostgresError,
|
|
1589
|
+
options,
|
|
1590
|
+
reserve,
|
|
1591
|
+
listen,
|
|
1592
|
+
begin,
|
|
1593
|
+
close,
|
|
1594
|
+
end
|
|
1595
|
+
});
|
|
1596
|
+
return sql;
|
|
1597
|
+
function Sql(handler2) {
|
|
1598
|
+
handler2.debug = options.debug;
|
|
1599
|
+
Object.entries(options.types).reduce((acc, [name, type]) => {
|
|
1600
|
+
acc[name] = (x) => new Parameter(x, type.to);
|
|
1601
|
+
return acc;
|
|
1602
|
+
}, typed);
|
|
1603
|
+
Object.assign(sql2, {
|
|
1604
|
+
types: typed,
|
|
1605
|
+
typed,
|
|
1606
|
+
unsafe,
|
|
1607
|
+
notify,
|
|
1608
|
+
array,
|
|
1609
|
+
json,
|
|
1610
|
+
file
|
|
1611
|
+
});
|
|
1612
|
+
return sql2;
|
|
1613
|
+
function typed(value, type) {
|
|
1614
|
+
return new Parameter(value, type);
|
|
1615
|
+
}
|
|
1616
|
+
function sql2(strings, ...args) {
|
|
1617
|
+
const query = strings && Array.isArray(strings.raw) ? new Query(strings, args, handler2, cancel) : typeof strings === "string" && !args.length ? new Identifier(options.transform.column.to ? options.transform.column.to(strings) : strings) : new Builder(strings, args);
|
|
1618
|
+
return query;
|
|
1619
|
+
}
|
|
1620
|
+
function unsafe(string, args = [], options2 = {}) {
|
|
1621
|
+
arguments.length === 2 && !Array.isArray(args) && (options2 = args, args = []);
|
|
1622
|
+
const query = new Query([string], args, handler2, cancel, {
|
|
1623
|
+
prepare: false,
|
|
1624
|
+
...options2,
|
|
1625
|
+
simple: "simple" in options2 ? options2.simple : args.length === 0
|
|
1626
|
+
});
|
|
1627
|
+
return query;
|
|
1628
|
+
}
|
|
1629
|
+
function file(path, args = [], options2 = {}) {
|
|
1630
|
+
arguments.length === 2 && !Array.isArray(args) && (options2 = args, args = []);
|
|
1631
|
+
const query = new Query([], args, (query2) => {
|
|
1632
|
+
fs.readFile(path, "utf8", (err, string) => {
|
|
1633
|
+
if (err)
|
|
1634
|
+
return query2.reject(err);
|
|
1635
|
+
query2.strings = [string];
|
|
1636
|
+
handler2(query2);
|
|
1637
|
+
});
|
|
1638
|
+
}, cancel, {
|
|
1639
|
+
...options2,
|
|
1640
|
+
simple: "simple" in options2 ? options2.simple : args.length === 0
|
|
1641
|
+
});
|
|
1642
|
+
return query;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
async function listen(name, fn, onlisten) {
|
|
1646
|
+
const listener = { fn, onlisten };
|
|
1647
|
+
const sql2 = listen.sql || (listen.sql = Postgres({
|
|
1648
|
+
...options,
|
|
1649
|
+
max: 1,
|
|
1650
|
+
idle_timeout: null,
|
|
1651
|
+
max_lifetime: null,
|
|
1652
|
+
fetch_types: false,
|
|
1653
|
+
onclose() {
|
|
1654
|
+
Object.entries(listen.channels).forEach(([name2, { listeners }]) => {
|
|
1655
|
+
delete listen.channels[name2];
|
|
1656
|
+
Promise.all(listeners.map((l) => listen(name2, l.fn, l.onlisten).catch(() => {})));
|
|
1657
|
+
});
|
|
1658
|
+
},
|
|
1659
|
+
onnotify(c, x) {
|
|
1660
|
+
c in listen.channels && listen.channels[c].listeners.forEach((l) => l.fn(x));
|
|
1661
|
+
}
|
|
1662
|
+
}));
|
|
1663
|
+
const channels = listen.channels || (listen.channels = {}), exists = name in channels;
|
|
1664
|
+
if (exists) {
|
|
1665
|
+
channels[name].listeners.push(listener);
|
|
1666
|
+
const result2 = await channels[name].result;
|
|
1667
|
+
listener.onlisten && listener.onlisten();
|
|
1668
|
+
return { state: result2.state, unlisten };
|
|
1669
|
+
}
|
|
1670
|
+
channels[name] = { result: sql2`listen ${sql2.unsafe('"' + name.replace(/"/g, '""') + '"')}`, listeners: [listener] };
|
|
1671
|
+
const result = await channels[name].result;
|
|
1672
|
+
listener.onlisten && listener.onlisten();
|
|
1673
|
+
return { state: result.state, unlisten };
|
|
1674
|
+
async function unlisten() {
|
|
1675
|
+
if (name in channels === false)
|
|
1676
|
+
return;
|
|
1677
|
+
channels[name].listeners = channels[name].listeners.filter((x) => x !== listener);
|
|
1678
|
+
if (channels[name].listeners.length)
|
|
1679
|
+
return;
|
|
1680
|
+
delete channels[name];
|
|
1681
|
+
return sql2`unlisten ${sql2.unsafe('"' + name.replace(/"/g, '""') + '"')}`;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
async function notify(channel, payload) {
|
|
1685
|
+
return await sql`select pg_notify(${channel}, ${"" + payload})`;
|
|
1686
|
+
}
|
|
1687
|
+
async function reserve() {
|
|
1688
|
+
const queue = queue_default();
|
|
1689
|
+
const c = open.length ? open.shift() : await new Promise((resolve, reject) => {
|
|
1690
|
+
const query = { reserve: resolve, reject };
|
|
1691
|
+
queries.push(query);
|
|
1692
|
+
closed.length && connect(closed.shift(), query);
|
|
1693
|
+
});
|
|
1694
|
+
move(c, reserved);
|
|
1695
|
+
c.reserved = () => queue.length ? c.execute(queue.shift()) : move(c, reserved);
|
|
1696
|
+
c.reserved.release = true;
|
|
1697
|
+
const sql2 = Sql(handler2);
|
|
1698
|
+
sql2.release = () => {
|
|
1699
|
+
c.reserved = null;
|
|
1700
|
+
onopen(c);
|
|
1701
|
+
};
|
|
1702
|
+
return sql2;
|
|
1703
|
+
function handler2(q) {
|
|
1704
|
+
c.queue === full ? queue.push(q) : c.execute(q) || move(c, full);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
async function begin(options2, fn) {
|
|
1708
|
+
!fn && (fn = options2, options2 = "");
|
|
1709
|
+
const queries2 = queue_default();
|
|
1710
|
+
let savepoints = 0, connection2, prepare = null;
|
|
1711
|
+
try {
|
|
1712
|
+
await sql.unsafe("begin " + options2.replace(/[^a-z ]/ig, ""), [], { onexecute }).execute();
|
|
1713
|
+
return await Promise.race([
|
|
1714
|
+
scope(connection2, fn),
|
|
1715
|
+
new Promise((_, reject) => connection2.onclose = reject)
|
|
1716
|
+
]);
|
|
1717
|
+
} catch (error) {
|
|
1718
|
+
throw error;
|
|
1719
|
+
}
|
|
1720
|
+
async function scope(c, fn2, name) {
|
|
1721
|
+
const sql2 = Sql(handler2);
|
|
1722
|
+
sql2.savepoint = savepoint;
|
|
1723
|
+
sql2.prepare = (x) => prepare = x.replace(/[^a-z0-9$-_. ]/gi);
|
|
1724
|
+
let uncaughtError, result;
|
|
1725
|
+
name && await sql2`savepoint ${sql2(name)}`;
|
|
1726
|
+
try {
|
|
1727
|
+
result = await new Promise((resolve, reject) => {
|
|
1728
|
+
const x = fn2(sql2);
|
|
1729
|
+
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve, reject);
|
|
1730
|
+
});
|
|
1731
|
+
if (uncaughtError)
|
|
1732
|
+
throw uncaughtError;
|
|
1733
|
+
} catch (e) {
|
|
1734
|
+
await (name ? sql2`rollback to ${sql2(name)}` : sql2`rollback`);
|
|
1735
|
+
throw e instanceof PostgresError && e.code === "25P02" && uncaughtError || e;
|
|
1736
|
+
}
|
|
1737
|
+
if (!name) {
|
|
1738
|
+
prepare ? await sql2`prepare transaction '${sql2.unsafe(prepare)}'` : await sql2`commit`;
|
|
1739
|
+
}
|
|
1740
|
+
return result;
|
|
1741
|
+
function savepoint(name2, fn3) {
|
|
1742
|
+
if (name2 && Array.isArray(name2.raw))
|
|
1743
|
+
return savepoint((sql3) => sql3.apply(sql3, arguments));
|
|
1744
|
+
arguments.length === 1 && (fn3 = name2, name2 = null);
|
|
1745
|
+
return scope(c, fn3, "s" + savepoints++ + (name2 ? "_" + name2 : ""));
|
|
1746
|
+
}
|
|
1747
|
+
function handler2(q) {
|
|
1748
|
+
q.catch((e) => uncaughtError || (uncaughtError = e));
|
|
1749
|
+
c.queue === full ? queries2.push(q) : c.execute(q) || move(c, full);
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
function onexecute(c) {
|
|
1753
|
+
connection2 = c;
|
|
1754
|
+
move(c, reserved);
|
|
1755
|
+
c.reserved = () => queries2.length ? c.execute(queries2.shift()) : move(c, reserved);
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
function move(c, queue) {
|
|
1759
|
+
c.queue.remove(c);
|
|
1760
|
+
queue.push(c);
|
|
1761
|
+
c.queue = queue;
|
|
1762
|
+
queue === open ? c.idleTimer.start() : c.idleTimer.cancel();
|
|
1763
|
+
return c;
|
|
1764
|
+
}
|
|
1765
|
+
function json(x) {
|
|
1766
|
+
return new Parameter(x, 3802);
|
|
1767
|
+
}
|
|
1768
|
+
function array(x, type) {
|
|
1769
|
+
if (!Array.isArray(x))
|
|
1770
|
+
return array(Array.from(arguments));
|
|
1771
|
+
return new Parameter(x, type || (x.length ? inferType(x) || 25 : 0), options.shared.typeArrayMap);
|
|
1772
|
+
}
|
|
1773
|
+
function handler(query) {
|
|
1774
|
+
if (ending)
|
|
1775
|
+
return query.reject(Errors.connection("CONNECTION_ENDED", options, options));
|
|
1776
|
+
if (open.length)
|
|
1777
|
+
return go(open.shift(), query);
|
|
1778
|
+
if (closed.length)
|
|
1779
|
+
return connect(closed.shift(), query);
|
|
1780
|
+
busy.length ? go(busy.shift(), query) : queries.push(query);
|
|
1781
|
+
}
|
|
1782
|
+
function go(c, query) {
|
|
1783
|
+
return c.execute(query) ? move(c, busy) : move(c, full);
|
|
1784
|
+
}
|
|
1785
|
+
function cancel(query) {
|
|
1786
|
+
return new Promise((resolve, reject) => {
|
|
1787
|
+
query.state ? query.active ? connection_default(options).cancel(query.state, resolve, reject) : query.cancelled = { resolve, reject } : (queries.remove(query), query.cancelled = true, query.reject(Errors.generic("57014", "canceling statement due to user request")), resolve());
|
|
1788
|
+
});
|
|
1789
|
+
}
|
|
1790
|
+
async function end({ timeout = null } = {}) {
|
|
1791
|
+
if (ending)
|
|
1792
|
+
return ending;
|
|
1793
|
+
await 1;
|
|
1794
|
+
let timer2;
|
|
1795
|
+
return ending = Promise.race([
|
|
1796
|
+
new Promise((r) => timeout !== null && (timer2 = setTimeout(destroy, timeout * 1000, r))),
|
|
1797
|
+
Promise.all(connections.map((c) => c.end()).concat(listen.sql ? listen.sql.end({ timeout: 0 }) : [], subscribe.sql ? subscribe.sql.end({ timeout: 0 }) : []))
|
|
1798
|
+
]).then(() => clearTimeout(timer2));
|
|
1799
|
+
}
|
|
1800
|
+
async function close() {
|
|
1801
|
+
await Promise.all(connections.map((c) => c.end()));
|
|
1802
|
+
}
|
|
1803
|
+
async function destroy(resolve) {
|
|
1804
|
+
await Promise.all(connections.map((c) => c.terminate()));
|
|
1805
|
+
while (queries.length)
|
|
1806
|
+
queries.shift().reject(Errors.connection("CONNECTION_DESTROYED", options));
|
|
1807
|
+
resolve();
|
|
1808
|
+
}
|
|
1809
|
+
function connect(c, query) {
|
|
1810
|
+
move(c, connecting);
|
|
1811
|
+
c.connect(query);
|
|
1812
|
+
return c;
|
|
1813
|
+
}
|
|
1814
|
+
function onend(c) {
|
|
1815
|
+
move(c, ended);
|
|
1816
|
+
}
|
|
1817
|
+
function onopen(c) {
|
|
1818
|
+
if (queries.length === 0)
|
|
1819
|
+
return move(c, open);
|
|
1820
|
+
let max = Math.ceil(queries.length / (connecting.length + 1)), ready = true;
|
|
1821
|
+
while (ready && queries.length && max-- > 0) {
|
|
1822
|
+
const query = queries.shift();
|
|
1823
|
+
if (query.reserve)
|
|
1824
|
+
return query.reserve(c);
|
|
1825
|
+
ready = c.execute(query);
|
|
1826
|
+
}
|
|
1827
|
+
ready ? move(c, busy) : move(c, full);
|
|
1828
|
+
}
|
|
1829
|
+
function onclose(c, e) {
|
|
1830
|
+
move(c, closed);
|
|
1831
|
+
c.reserved = null;
|
|
1832
|
+
c.onclose && (c.onclose(e), c.onclose = null);
|
|
1833
|
+
options.onclose && options.onclose(c.id);
|
|
1834
|
+
queries.length && connect(c, queries.shift());
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
function parseOptions(a, b2) {
|
|
1838
|
+
if (a && a.shared)
|
|
1839
|
+
return a;
|
|
1840
|
+
const env = process.env, o = (!a || typeof a === "string" ? b2 : a) || {}, { url, multihost } = parseUrl(a), query = [...url.searchParams].reduce((a2, [b3, c]) => (a2[b3] = c, a2), {}), host = o.hostname || o.host || multihost || url.hostname || env.PGHOST || "localhost", port = o.port || url.port || env.PGPORT || 5432, user = o.user || o.username || url.username || env.PGUSERNAME || env.PGUSER || osUsername();
|
|
1841
|
+
o.no_prepare && (o.prepare = false);
|
|
1842
|
+
query.sslmode && (query.ssl = query.sslmode, delete query.sslmode);
|
|
1843
|
+
"timeout" in o && (console.log("The timeout option is deprecated, use idle_timeout instead"), o.idle_timeout = o.timeout);
|
|
1844
|
+
query.sslrootcert === "system" && (query.ssl = "verify-full");
|
|
1845
|
+
const ints = ["idle_timeout", "connect_timeout", "max_lifetime", "max_pipeline", "backoff", "keep_alive"];
|
|
1846
|
+
const defaults = {
|
|
1847
|
+
max: 10,
|
|
1848
|
+
ssl: false,
|
|
1849
|
+
idle_timeout: null,
|
|
1850
|
+
connect_timeout: 30,
|
|
1851
|
+
max_lifetime,
|
|
1852
|
+
max_pipeline: 100,
|
|
1853
|
+
backoff,
|
|
1854
|
+
keep_alive: 60,
|
|
1855
|
+
prepare: true,
|
|
1856
|
+
debug: false,
|
|
1857
|
+
fetch_types: true,
|
|
1858
|
+
publications: "alltables",
|
|
1859
|
+
target_session_attrs: null
|
|
1860
|
+
};
|
|
1861
|
+
return {
|
|
1862
|
+
host: Array.isArray(host) ? host : host.split(",").map((x) => x.split(":")[0]),
|
|
1863
|
+
port: Array.isArray(port) ? port : host.split(",").map((x) => parseInt(x.split(":")[1] || port)),
|
|
1864
|
+
path: o.path || host.indexOf("/") > -1 && host + "/.s.PGSQL." + port,
|
|
1865
|
+
database: o.database || o.db || (url.pathname || "").slice(1) || env.PGDATABASE || user,
|
|
1866
|
+
user,
|
|
1867
|
+
pass: o.pass || o.password || url.password || env.PGPASSWORD || "",
|
|
1868
|
+
...Object.entries(defaults).reduce((acc, [k, d]) => {
|
|
1869
|
+
const value = k in o ? o[k] : (k in query) ? query[k] === "disable" || query[k] === "false" ? false : query[k] : env["PG" + k.toUpperCase()] || d;
|
|
1870
|
+
acc[k] = typeof value === "string" && ints.includes(k) ? +value : value;
|
|
1871
|
+
return acc;
|
|
1872
|
+
}, {}),
|
|
1873
|
+
connection: {
|
|
1874
|
+
application_name: env.PGAPPNAME || "postgres.js",
|
|
1875
|
+
...o.connection,
|
|
1876
|
+
...Object.entries(query).reduce((acc, [k, v]) => ((k in defaults) || (acc[k] = v), acc), {})
|
|
1877
|
+
},
|
|
1878
|
+
types: o.types || {},
|
|
1879
|
+
target_session_attrs: tsa(o, url, env),
|
|
1880
|
+
onnotice: o.onnotice,
|
|
1881
|
+
onnotify: o.onnotify,
|
|
1882
|
+
onclose: o.onclose,
|
|
1883
|
+
onparameter: o.onparameter,
|
|
1884
|
+
socket: o.socket,
|
|
1885
|
+
transform: parseTransform(o.transform || { undefined: undefined }),
|
|
1886
|
+
parameters: {},
|
|
1887
|
+
shared: { retries: 0, typeArrayMap: {} },
|
|
1888
|
+
...mergeUserTypes(o.types)
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
function tsa(o, url, env) {
|
|
1892
|
+
const x = o.target_session_attrs || url.searchParams.get("target_session_attrs") || env.PGTARGETSESSIONATTRS;
|
|
1893
|
+
if (!x || ["read-write", "read-only", "primary", "standby", "prefer-standby"].includes(x))
|
|
1894
|
+
return x;
|
|
1895
|
+
throw new Error("target_session_attrs " + x + " is not supported");
|
|
1896
|
+
}
|
|
1897
|
+
function backoff(retries) {
|
|
1898
|
+
return (0.5 + Math.random() / 2) * Math.min(3 ** retries / 100, 20);
|
|
1899
|
+
}
|
|
1900
|
+
function max_lifetime() {
|
|
1901
|
+
return 60 * (30 + Math.random() * 30);
|
|
1902
|
+
}
|
|
1903
|
+
function parseTransform(x) {
|
|
1904
|
+
return {
|
|
1905
|
+
undefined: x.undefined,
|
|
1906
|
+
column: {
|
|
1907
|
+
from: typeof x.column === "function" ? x.column : x.column && x.column.from,
|
|
1908
|
+
to: x.column && x.column.to
|
|
1909
|
+
},
|
|
1910
|
+
value: {
|
|
1911
|
+
from: typeof x.value === "function" ? x.value : x.value && x.value.from,
|
|
1912
|
+
to: x.value && x.value.to
|
|
1913
|
+
},
|
|
1914
|
+
row: {
|
|
1915
|
+
from: typeof x.row === "function" ? x.row : x.row && x.row.from,
|
|
1916
|
+
to: x.row && x.row.to
|
|
1917
|
+
}
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
function parseUrl(url) {
|
|
1921
|
+
if (!url || typeof url !== "string")
|
|
1922
|
+
return { url: { searchParams: new Map } };
|
|
1923
|
+
let host = url;
|
|
1924
|
+
host = host.slice(host.indexOf("://") + 3).split(/[?/]/)[0];
|
|
1925
|
+
host = decodeURIComponent(host.slice(host.indexOf("@") + 1));
|
|
1926
|
+
const urlObj = new URL(url.replace(host, host.split(",")[0]));
|
|
1927
|
+
return {
|
|
1928
|
+
url: {
|
|
1929
|
+
username: decodeURIComponent(urlObj.username),
|
|
1930
|
+
password: decodeURIComponent(urlObj.password),
|
|
1931
|
+
host: urlObj.host,
|
|
1932
|
+
hostname: urlObj.hostname,
|
|
1933
|
+
port: urlObj.port,
|
|
1934
|
+
pathname: urlObj.pathname,
|
|
1935
|
+
searchParams: urlObj.searchParams
|
|
1936
|
+
},
|
|
1937
|
+
multihost: host.indexOf(",") > -1 && host
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
function osUsername() {
|
|
1941
|
+
try {
|
|
1942
|
+
return os.userInfo().username;
|
|
1943
|
+
} catch (_) {
|
|
1944
|
+
return process.env.USERNAME || process.env.USER || process.env.LOGNAME;
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// db.ts
|
|
1949
|
+
var DATABASE_URL = process.env.OPENCODE_DATABASE_URL || "postgres://opencode:opencode@postgres:5432/opencode";
|
|
1950
|
+
var sql = src_default(DATABASE_URL, {
|
|
1951
|
+
max: 10,
|
|
1952
|
+
idle_timeout: 0,
|
|
1953
|
+
connect_timeout: 30,
|
|
1954
|
+
onnotice: () => {}
|
|
1955
|
+
});
|
|
1956
|
+
async function ensureConnection() {
|
|
1957
|
+
try {
|
|
1958
|
+
await sql`SELECT 1`;
|
|
1959
|
+
return true;
|
|
1960
|
+
} catch (error) {
|
|
1961
|
+
console.error("[database] Database connection failed:", error);
|
|
1962
|
+
return false;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
// index.ts
|
|
1967
|
+
var pendingExecutions = new Map;
|
|
1968
|
+
var callIdToPartId = new Map;
|
|
1969
|
+
var pendingUserMessages = new Map;
|
|
1970
|
+
var tokensCountedBySession = new Map;
|
|
1971
|
+
function generateCorrelationId() {
|
|
1972
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1973
|
+
}
|
|
1974
|
+
var DatabasePlugin = async ({ client }) => {
|
|
1975
|
+
const connected = await ensureConnection();
|
|
1976
|
+
if (!connected) {
|
|
1977
|
+
await client.app.log({
|
|
1978
|
+
body: {
|
|
1979
|
+
service: "database",
|
|
1980
|
+
level: "warn",
|
|
1981
|
+
message: "Plugin disabled - no database connection"
|
|
1982
|
+
}
|
|
1983
|
+
});
|
|
1984
|
+
return {};
|
|
1985
|
+
}
|
|
1986
|
+
return {
|
|
1987
|
+
event: async ({ event }) => {
|
|
1988
|
+
const props = event.properties;
|
|
1989
|
+
try {
|
|
1990
|
+
switch (event.type) {
|
|
1991
|
+
case "session.created": {
|
|
1992
|
+
const info = props.info;
|
|
1993
|
+
await sql`
|
|
1994
|
+
INSERT INTO sessions (id, title, parent_id, project_id, directory, status, created_at)
|
|
1995
|
+
VALUES (
|
|
1996
|
+
${info.id},
|
|
1997
|
+
${info.title || null},
|
|
1998
|
+
${info.parentID || null},
|
|
1999
|
+
${info.projectID || null},
|
|
2000
|
+
${info.directory || null},
|
|
2001
|
+
'created',
|
|
2002
|
+
NOW()
|
|
2003
|
+
)
|
|
2004
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
2005
|
+
title = COALESCE(${info.title || null}, sessions.title),
|
|
2006
|
+
parent_id = COALESCE(${info.parentID || null}, sessions.parent_id),
|
|
2007
|
+
project_id = COALESCE(${info.projectID || null}, sessions.project_id),
|
|
2008
|
+
directory = COALESCE(${info.directory || null}, sessions.directory)
|
|
2009
|
+
`;
|
|
2010
|
+
break;
|
|
2011
|
+
}
|
|
2012
|
+
case "session.updated": {
|
|
2013
|
+
const info = props.info;
|
|
2014
|
+
await sql`
|
|
2015
|
+
UPDATE sessions
|
|
2016
|
+
SET title = COALESCE(${info.title || null}, title),
|
|
2017
|
+
share_url = COALESCE(${info.share?.url || null}, share_url)
|
|
2018
|
+
WHERE id = ${info.id}
|
|
2019
|
+
`;
|
|
2020
|
+
break;
|
|
2021
|
+
}
|
|
2022
|
+
case "session.deleted": {
|
|
2023
|
+
const info = props.info;
|
|
2024
|
+
await sql`
|
|
2025
|
+
UPDATE sessions
|
|
2026
|
+
SET deleted_at = NOW(), status = 'deleted'
|
|
2027
|
+
WHERE id = ${info.id}
|
|
2028
|
+
`;
|
|
2029
|
+
tokensCountedBySession.delete(info.id);
|
|
2030
|
+
break;
|
|
2031
|
+
}
|
|
2032
|
+
case "session.idle": {
|
|
2033
|
+
const sessionID = props.sessionID;
|
|
2034
|
+
await sql`
|
|
2035
|
+
UPDATE sessions
|
|
2036
|
+
SET status = 'idle', updated_at = NOW()
|
|
2037
|
+
WHERE id = ${sessionID}
|
|
2038
|
+
`;
|
|
2039
|
+
break;
|
|
2040
|
+
}
|
|
2041
|
+
case "session.error": {
|
|
2042
|
+
const sessionID = props.sessionID;
|
|
2043
|
+
const error = props.error;
|
|
2044
|
+
if (sessionID) {
|
|
2045
|
+
await sql`
|
|
2046
|
+
INSERT INTO session_errors (session_id, error_type, error_message, error_data)
|
|
2047
|
+
VALUES (
|
|
2048
|
+
${sessionID},
|
|
2049
|
+
${error?.name || "unknown"},
|
|
2050
|
+
${error?.data?.message || null},
|
|
2051
|
+
${error ? sql.json(error) : null}
|
|
2052
|
+
)
|
|
2053
|
+
`;
|
|
2054
|
+
await sql`
|
|
2055
|
+
UPDATE sessions SET status = 'error' WHERE id = ${sessionID}
|
|
2056
|
+
`;
|
|
2057
|
+
await client.app.log({
|
|
2058
|
+
body: {
|
|
2059
|
+
service: "database",
|
|
2060
|
+
level: "info",
|
|
2061
|
+
message: "Session error",
|
|
2062
|
+
extra: { sessionID, errorMessage: error?.data?.message }
|
|
2063
|
+
}
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
break;
|
|
2067
|
+
}
|
|
2068
|
+
case "session.compacted": {
|
|
2069
|
+
const sessionID = props.sessionID;
|
|
2070
|
+
const [sessionState] = await sql`
|
|
2071
|
+
SELECT context_tokens, input_tokens, output_tokens,
|
|
2072
|
+
cache_read_tokens, cache_write_tokens, reasoning_tokens, estimated_cost
|
|
2073
|
+
FROM sessions WHERE id = ${sessionID}
|
|
2074
|
+
`;
|
|
2075
|
+
if (sessionState) {
|
|
2076
|
+
await sql`
|
|
2077
|
+
INSERT INTO compactions (
|
|
2078
|
+
session_id,
|
|
2079
|
+
context_tokens_before,
|
|
2080
|
+
cumulative_input_tokens,
|
|
2081
|
+
cumulative_output_tokens,
|
|
2082
|
+
cumulative_cache_read,
|
|
2083
|
+
cumulative_cache_write,
|
|
2084
|
+
cumulative_reasoning,
|
|
2085
|
+
cumulative_cost
|
|
2086
|
+
)
|
|
2087
|
+
VALUES (
|
|
2088
|
+
${sessionID},
|
|
2089
|
+
${sessionState.context_tokens || 0},
|
|
2090
|
+
${sessionState.input_tokens || 0},
|
|
2091
|
+
${sessionState.output_tokens || 0},
|
|
2092
|
+
${sessionState.cache_read_tokens || 0},
|
|
2093
|
+
${sessionState.cache_write_tokens || 0},
|
|
2094
|
+
${sessionState.reasoning_tokens || 0},
|
|
2095
|
+
${parseFloat(sessionState.estimated_cost || "0")}
|
|
2096
|
+
)
|
|
2097
|
+
`;
|
|
2098
|
+
}
|
|
2099
|
+
await sql`
|
|
2100
|
+
UPDATE sessions
|
|
2101
|
+
SET
|
|
2102
|
+
status = 'compacted',
|
|
2103
|
+
peak_context_tokens = GREATEST(peak_context_tokens, context_tokens),
|
|
2104
|
+
context_tokens = 0,
|
|
2105
|
+
compaction_count = compaction_count + 1
|
|
2106
|
+
WHERE id = ${sessionID}
|
|
2107
|
+
`;
|
|
2108
|
+
tokensCountedBySession.delete(sessionID);
|
|
2109
|
+
break;
|
|
2110
|
+
}
|
|
2111
|
+
case "message.updated": {
|
|
2112
|
+
const info = props.info;
|
|
2113
|
+
await sql`
|
|
2114
|
+
INSERT INTO sessions (id, status, created_at, updated_at)
|
|
2115
|
+
VALUES (${info.sessionID}, 'active', NOW(), NOW())
|
|
2116
|
+
ON CONFLICT (id) DO UPDATE SET updated_at = NOW()
|
|
2117
|
+
`;
|
|
2118
|
+
let messageContent = info.parts;
|
|
2119
|
+
let textContent = null;
|
|
2120
|
+
let systemPrompt = info.system || null;
|
|
2121
|
+
if (info.role === "user") {
|
|
2122
|
+
const pending = pendingUserMessages.get(info.sessionID);
|
|
2123
|
+
if (pending) {
|
|
2124
|
+
if (!messageContent) {
|
|
2125
|
+
messageContent = pending.parts;
|
|
2126
|
+
textContent = messageContent.filter((p) => p.type === "text" && p.text).map((p) => p.text).join(`
|
|
2127
|
+
`) || null;
|
|
2128
|
+
}
|
|
2129
|
+
if (!systemPrompt && pending.systemPrompt) {
|
|
2130
|
+
systemPrompt = pending.systemPrompt;
|
|
2131
|
+
}
|
|
2132
|
+
pendingUserMessages.delete(info.sessionID);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
const modelProvider = info.providerID || info.model?.providerID || null;
|
|
2136
|
+
const modelId = info.modelID || info.model?.modelID || null;
|
|
2137
|
+
await sql`
|
|
2138
|
+
INSERT INTO messages (id, session_id, role, model_provider, model_id, text, summary, content, system_prompt, created_at)
|
|
2139
|
+
VALUES (
|
|
2140
|
+
${info.id},
|
|
2141
|
+
${info.sessionID},
|
|
2142
|
+
${info.role},
|
|
2143
|
+
${modelProvider},
|
|
2144
|
+
${modelId},
|
|
2145
|
+
${textContent},
|
|
2146
|
+
${info.summary?.title || null},
|
|
2147
|
+
${messageContent ? sql.json(messageContent) : null},
|
|
2148
|
+
${systemPrompt},
|
|
2149
|
+
NOW()
|
|
2150
|
+
)
|
|
2151
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
2152
|
+
role = ${info.role},
|
|
2153
|
+
model_provider = COALESCE(EXCLUDED.model_provider, messages.model_provider),
|
|
2154
|
+
model_id = COALESCE(EXCLUDED.model_id, messages.model_id),
|
|
2155
|
+
text = COALESCE(${textContent}, messages.text),
|
|
2156
|
+
summary = COALESCE(${info.summary?.title || null}, messages.summary),
|
|
2157
|
+
content = COALESCE(${messageContent ? sql.json(messageContent) : null}, messages.content),
|
|
2158
|
+
system_prompt = COALESCE(${systemPrompt}, messages.system_prompt)
|
|
2159
|
+
`;
|
|
2160
|
+
const sessionTokens = tokensCountedBySession.get(info.sessionID) || new Set;
|
|
2161
|
+
if (info.role === "assistant" && info.tokens && !sessionTokens.has(info.id)) {
|
|
2162
|
+
const inputTokens = info.tokens.input ?? 0;
|
|
2163
|
+
const outputTokens = info.tokens.output ?? 0;
|
|
2164
|
+
const reasoningTokens = info.tokens.reasoning ?? 0;
|
|
2165
|
+
const cacheRead = info.tokens.cache?.read ?? 0;
|
|
2166
|
+
const cacheWrite = info.tokens.cache?.write ?? 0;
|
|
2167
|
+
if (inputTokens > 0 || outputTokens > 0) {
|
|
2168
|
+
sessionTokens.add(info.id);
|
|
2169
|
+
tokensCountedBySession.set(info.sessionID, sessionTokens);
|
|
2170
|
+
const contextSize = inputTokens + cacheRead;
|
|
2171
|
+
await sql`
|
|
2172
|
+
UPDATE sessions
|
|
2173
|
+
SET
|
|
2174
|
+
input_tokens = input_tokens + ${inputTokens},
|
|
2175
|
+
output_tokens = output_tokens + ${outputTokens},
|
|
2176
|
+
reasoning_tokens = reasoning_tokens + ${reasoningTokens},
|
|
2177
|
+
cache_read_tokens = cache_read_tokens + ${cacheRead},
|
|
2178
|
+
cache_write_tokens = cache_write_tokens + ${cacheWrite},
|
|
2179
|
+
context_tokens = ${contextSize},
|
|
2180
|
+
peak_context_tokens = GREATEST(peak_context_tokens, ${contextSize}),
|
|
2181
|
+
model_provider = COALESCE(${modelProvider}, model_provider),
|
|
2182
|
+
model_id = COALESCE(${modelId}, model_id)
|
|
2183
|
+
WHERE id = ${info.sessionID}
|
|
2184
|
+
`;
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
break;
|
|
2188
|
+
}
|
|
2189
|
+
case "message.removed": {
|
|
2190
|
+
const messageID = props.messageID;
|
|
2191
|
+
await sql`
|
|
2192
|
+
DELETE FROM messages WHERE id = ${messageID}
|
|
2193
|
+
`;
|
|
2194
|
+
break;
|
|
2195
|
+
}
|
|
2196
|
+
case "message.part.updated": {
|
|
2197
|
+
const part = props.part;
|
|
2198
|
+
const toolName = part.type === "tool" ? part.tool || null : null;
|
|
2199
|
+
const textContent = part.text || null;
|
|
2200
|
+
if (part.type === "tool" && part.callID) {
|
|
2201
|
+
callIdToPartId.set(part.callID, part.id);
|
|
2202
|
+
const pending = pendingExecutions.get(part.callID);
|
|
2203
|
+
if (pending) {
|
|
2204
|
+
pending.partId = part.id;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
if (part.type === "step-finish" && part.cost !== undefined) {
|
|
2208
|
+
await sql`
|
|
2209
|
+
UPDATE sessions
|
|
2210
|
+
SET estimated_cost = estimated_cost + ${part.cost}
|
|
2211
|
+
WHERE id = ${part.sessionID}
|
|
2212
|
+
`;
|
|
2213
|
+
}
|
|
2214
|
+
await sql`
|
|
2215
|
+
INSERT INTO messages (id, session_id, role, created_at)
|
|
2216
|
+
VALUES (${part.messageID}, ${part.sessionID}, 'assistant', NOW())
|
|
2217
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
2218
|
+
role = COALESCE(messages.role, 'assistant')
|
|
2219
|
+
`;
|
|
2220
|
+
await sql`
|
|
2221
|
+
INSERT INTO sessions (id, status, created_at)
|
|
2222
|
+
VALUES (${part.sessionID}, 'active', NOW())
|
|
2223
|
+
ON CONFLICT (id) DO NOTHING
|
|
2224
|
+
`;
|
|
2225
|
+
const isStreamingTextPart = part.type === "text" || part.type === "reasoning";
|
|
2226
|
+
const partAsJson = { ...part };
|
|
2227
|
+
if (isStreamingTextPart) {
|
|
2228
|
+
await sql`
|
|
2229
|
+
INSERT INTO message_parts (id, message_id, part_type, tool_name, text, content, created_at)
|
|
2230
|
+
VALUES (
|
|
2231
|
+
${part.id},
|
|
2232
|
+
${part.messageID},
|
|
2233
|
+
${part.type},
|
|
2234
|
+
${toolName},
|
|
2235
|
+
${textContent},
|
|
2236
|
+
${sql.json(partAsJson)},
|
|
2237
|
+
NOW()
|
|
2238
|
+
)
|
|
2239
|
+
ON CONFLICT (id) DO NOTHING
|
|
2240
|
+
`;
|
|
2241
|
+
if (textContent) {
|
|
2242
|
+
await sql`
|
|
2243
|
+
UPDATE message_parts
|
|
2244
|
+
SET
|
|
2245
|
+
tool_name = COALESCE(${toolName}, tool_name),
|
|
2246
|
+
text = ${textContent},
|
|
2247
|
+
content = ${sql.json(partAsJson)}
|
|
2248
|
+
WHERE id = ${part.id}
|
|
2249
|
+
AND (text IS NULL OR LENGTH(text) < LENGTH(${textContent}))
|
|
2250
|
+
`;
|
|
2251
|
+
}
|
|
2252
|
+
} else {
|
|
2253
|
+
const statusPriority = {
|
|
2254
|
+
pending: 1,
|
|
2255
|
+
running: 2,
|
|
2256
|
+
completed: 3,
|
|
2257
|
+
error: 3
|
|
2258
|
+
};
|
|
2259
|
+
const currentStatus = part.state?.status || "pending";
|
|
2260
|
+
const currentPriority = statusPriority[currentStatus] || 0;
|
|
2261
|
+
await sql`
|
|
2262
|
+
INSERT INTO message_parts (id, message_id, part_type, tool_name, text, content, created_at)
|
|
2263
|
+
VALUES (
|
|
2264
|
+
${part.id},
|
|
2265
|
+
${part.messageID},
|
|
2266
|
+
${part.type},
|
|
2267
|
+
${toolName},
|
|
2268
|
+
${textContent},
|
|
2269
|
+
${sql.json(partAsJson)},
|
|
2270
|
+
NOW()
|
|
2271
|
+
)
|
|
2272
|
+
ON CONFLICT (id) DO NOTHING
|
|
2273
|
+
`;
|
|
2274
|
+
await sql`
|
|
2275
|
+
UPDATE message_parts
|
|
2276
|
+
SET
|
|
2277
|
+
tool_name = COALESCE(${toolName}, tool_name),
|
|
2278
|
+
text = COALESCE(${textContent}, text),
|
|
2279
|
+
content = ${sql.json(partAsJson)}
|
|
2280
|
+
WHERE id = ${part.id}
|
|
2281
|
+
AND ${currentPriority} >= COALESCE(
|
|
2282
|
+
CASE (content->'state'->>'status')
|
|
2283
|
+
WHEN 'pending' THEN 1
|
|
2284
|
+
WHEN 'running' THEN 2
|
|
2285
|
+
WHEN 'completed' THEN 3
|
|
2286
|
+
WHEN 'error' THEN 3
|
|
2287
|
+
ELSE 0
|
|
2288
|
+
END, 0
|
|
2289
|
+
)
|
|
2290
|
+
`;
|
|
2291
|
+
}
|
|
2292
|
+
if (part.type === "text" && textContent) {
|
|
2293
|
+
await sql`
|
|
2294
|
+
UPDATE messages
|
|
2295
|
+
SET text = ${textContent}
|
|
2296
|
+
WHERE id = ${part.messageID}
|
|
2297
|
+
AND (text IS NULL OR LENGTH(text) < LENGTH(${textContent}))
|
|
2298
|
+
`;
|
|
2299
|
+
}
|
|
2300
|
+
break;
|
|
2301
|
+
}
|
|
2302
|
+
case "message.part.removed": {
|
|
2303
|
+
const partID = props.partID;
|
|
2304
|
+
await sql`
|
|
2305
|
+
DELETE FROM message_parts WHERE id = ${partID}
|
|
2306
|
+
`;
|
|
2307
|
+
break;
|
|
2308
|
+
}
|
|
2309
|
+
case "command.executed": {
|
|
2310
|
+
const name = props.name;
|
|
2311
|
+
const sessionID = props.sessionID;
|
|
2312
|
+
const args = props.arguments;
|
|
2313
|
+
await sql`
|
|
2314
|
+
INSERT INTO commands (session_id, command_name, command_args, created_at)
|
|
2315
|
+
VALUES (
|
|
2316
|
+
${sessionID},
|
|
2317
|
+
${name},
|
|
2318
|
+
${args || null},
|
|
2319
|
+
NOW()
|
|
2320
|
+
)
|
|
2321
|
+
`;
|
|
2322
|
+
break;
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
} catch (error) {
|
|
2326
|
+
await client.app.log({
|
|
2327
|
+
body: {
|
|
2328
|
+
service: "database",
|
|
2329
|
+
level: "error",
|
|
2330
|
+
message: "Error recording event",
|
|
2331
|
+
extra: { eventType: event.type, error: String(error) }
|
|
2332
|
+
}
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2335
|
+
},
|
|
2336
|
+
"chat.message": async (input, output) => {
|
|
2337
|
+
try {
|
|
2338
|
+
await sql`
|
|
2339
|
+
UPDATE sessions SET status = 'active', updated_at = NOW()
|
|
2340
|
+
WHERE id = ${input.sessionID}
|
|
2341
|
+
`;
|
|
2342
|
+
const systemPrompt = output.message?.system;
|
|
2343
|
+
if (output.parts && output.parts.length > 0) {
|
|
2344
|
+
pendingUserMessages.set(input.sessionID, {
|
|
2345
|
+
parts: output.parts,
|
|
2346
|
+
systemPrompt,
|
|
2347
|
+
timestamp: Date.now()
|
|
2348
|
+
});
|
|
2349
|
+
} else if (systemPrompt) {
|
|
2350
|
+
pendingUserMessages.set(input.sessionID, {
|
|
2351
|
+
parts: [],
|
|
2352
|
+
systemPrompt,
|
|
2353
|
+
timestamp: Date.now()
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2356
|
+
} catch (error) {
|
|
2357
|
+
await client.app.log({
|
|
2358
|
+
body: {
|
|
2359
|
+
service: "database",
|
|
2360
|
+
level: "error",
|
|
2361
|
+
message: "Error in chat.message",
|
|
2362
|
+
extra: { error: String(error) }
|
|
2363
|
+
}
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
},
|
|
2367
|
+
"tool.execute.before": async (input, output) => {
|
|
2368
|
+
try {
|
|
2369
|
+
const correlationId = generateCorrelationId();
|
|
2370
|
+
const startedAt = new Date;
|
|
2371
|
+
pendingExecutions.set(input.callID, {
|
|
2372
|
+
correlationId,
|
|
2373
|
+
sessionId: input.sessionID,
|
|
2374
|
+
toolName: input.tool,
|
|
2375
|
+
args: output.args || {},
|
|
2376
|
+
startedAt
|
|
2377
|
+
});
|
|
2378
|
+
await sql`
|
|
2379
|
+
INSERT INTO tool_executions (
|
|
2380
|
+
correlation_id,
|
|
2381
|
+
session_id,
|
|
2382
|
+
tool_name,
|
|
2383
|
+
args,
|
|
2384
|
+
started_at,
|
|
2385
|
+
created_at
|
|
2386
|
+
)
|
|
2387
|
+
VALUES (
|
|
2388
|
+
${correlationId},
|
|
2389
|
+
${input.sessionID},
|
|
2390
|
+
${input.tool},
|
|
2391
|
+
${output.args ?? null},
|
|
2392
|
+
${startedAt},
|
|
2393
|
+
NOW()
|
|
2394
|
+
)
|
|
2395
|
+
`;
|
|
2396
|
+
} catch (error) {
|
|
2397
|
+
await client.app.log({
|
|
2398
|
+
body: {
|
|
2399
|
+
service: "database",
|
|
2400
|
+
level: "error",
|
|
2401
|
+
message: "Error recording tool start",
|
|
2402
|
+
extra: { error: String(error) }
|
|
2403
|
+
}
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
},
|
|
2407
|
+
"tool.execute.after": async (input, output) => {
|
|
2408
|
+
try {
|
|
2409
|
+
const completedAt = new Date;
|
|
2410
|
+
const pending = pendingExecutions.get(input.callID);
|
|
2411
|
+
if (pending) {
|
|
2412
|
+
const durationMs = completedAt.getTime() - pending.startedAt.getTime();
|
|
2413
|
+
await sql`
|
|
2414
|
+
UPDATE tool_executions
|
|
2415
|
+
SET
|
|
2416
|
+
result = ${output.output ?? null},
|
|
2417
|
+
completed_at = ${completedAt},
|
|
2418
|
+
duration_ms = ${durationMs},
|
|
2419
|
+
success = true
|
|
2420
|
+
WHERE correlation_id = ${pending.correlationId}
|
|
2421
|
+
`;
|
|
2422
|
+
const partId = pending.partId || callIdToPartId.get(input.callID);
|
|
2423
|
+
if (partId && output.output) {
|
|
2424
|
+
const outputJson = JSON.stringify(output.output);
|
|
2425
|
+
await sql`
|
|
2426
|
+
UPDATE message_parts
|
|
2427
|
+
SET content = jsonb_set(
|
|
2428
|
+
COALESCE(content, '{"state":{}}'::jsonb),
|
|
2429
|
+
'{state,output}',
|
|
2430
|
+
${outputJson}::jsonb
|
|
2431
|
+
)
|
|
2432
|
+
WHERE id = ${partId}
|
|
2433
|
+
AND (content->'state'->>'output') IS NULL
|
|
2434
|
+
`;
|
|
2435
|
+
}
|
|
2436
|
+
pendingExecutions.delete(input.callID);
|
|
2437
|
+
} else {
|
|
2438
|
+
await sql`
|
|
2439
|
+
INSERT INTO tool_executions (
|
|
2440
|
+
correlation_id,
|
|
2441
|
+
session_id,
|
|
2442
|
+
tool_name,
|
|
2443
|
+
args,
|
|
2444
|
+
result,
|
|
2445
|
+
completed_at,
|
|
2446
|
+
success,
|
|
2447
|
+
created_at
|
|
2448
|
+
)
|
|
2449
|
+
VALUES (
|
|
2450
|
+
${generateCorrelationId()},
|
|
2451
|
+
${input.sessionID},
|
|
2452
|
+
${input.tool},
|
|
2453
|
+
${output.metadata ?? null},
|
|
2454
|
+
${output.output ?? null},
|
|
2455
|
+
${completedAt},
|
|
2456
|
+
true,
|
|
2457
|
+
NOW()
|
|
2458
|
+
)
|
|
2459
|
+
`;
|
|
2460
|
+
const partId = callIdToPartId.get(input.callID);
|
|
2461
|
+
if (partId && output.output) {
|
|
2462
|
+
const outputJson = JSON.stringify(output.output);
|
|
2463
|
+
await sql`
|
|
2464
|
+
UPDATE message_parts
|
|
2465
|
+
SET content = jsonb_set(
|
|
2466
|
+
COALESCE(content, '{"state":{}}'::jsonb),
|
|
2467
|
+
'{state,output}',
|
|
2468
|
+
${outputJson}::jsonb
|
|
2469
|
+
)
|
|
2470
|
+
WHERE id = ${partId}
|
|
2471
|
+
AND (content->'state'->>'output') IS NULL
|
|
2472
|
+
`;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
callIdToPartId.delete(input.callID);
|
|
2476
|
+
} catch (error) {
|
|
2477
|
+
await client.app.log({
|
|
2478
|
+
body: {
|
|
2479
|
+
service: "database",
|
|
2480
|
+
level: "error",
|
|
2481
|
+
message: "Error recording tool completion",
|
|
2482
|
+
extra: { error: String(error) }
|
|
2483
|
+
}
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
};
|
|
2488
|
+
};
|
|
2489
|
+
export {
|
|
2490
|
+
generateCorrelationId,
|
|
2491
|
+
DatabasePlugin
|
|
2492
|
+
};
|