@m2k-5f/pgtx 2.8.0 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -47
- package/dist/clauses/array.clause.d.ts.map +1 -1
- package/dist/clauses/array.clause.js +0 -5
- package/dist/clauses/iden.caluse.d.ts.map +1 -1
- package/dist/clauses/iden.caluse.js +0 -2
- package/dist/clauses/insert.clause.d.ts.map +1 -1
- package/dist/clauses/insert.clause.js +5 -6
- package/dist/clauses/literal.clause.d.ts.map +1 -1
- package/dist/clauses/literal.clause.js +0 -3
- package/dist/clauses/update.clause.d.ts.map +1 -1
- package/dist/clauses/update.clause.js +0 -2
- package/dist/clauses/where.clause.d.ts.map +1 -1
- package/dist/clauses/where.clause.js +0 -2
- package/dist/connection.d.ts +7 -3
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +147 -116
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +40 -9
- package/dist/index.d.ts +30 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/pool.d.ts +2 -0
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +6 -0
- package/dist/protocol/connection-request-writer.d.ts +1 -1
- package/dist/protocol/connection-request-writer.d.ts.map +1 -1
- package/dist/protocol/connection-request-writer.js +1 -3
- package/dist/protocol/connection-response-reader.d.ts +1 -1
- package/dist/protocol/connection-response-reader.js +1 -1
- package/dist/protocol/constants.js +8 -8
- package/dist/protocol/types.d.ts +3 -1
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/types.js +91 -1
- package/dist/query.d.ts +9 -11
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +8 -10
- package/dist/transaction.d.ts +10 -2
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +78 -23
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +0 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -46
- package/package.json +1 -1
package/dist/connection.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Queue } from "./queue";
|
|
|
6
6
|
import { CollectQuery, StreamQuery, ExecuteQuery, ParseQuery } from "./query";
|
|
7
7
|
import { sql } from ".";
|
|
8
8
|
import { Begin, Future, Ok } from 'fluent-future';
|
|
9
|
-
import { ErrConnectionClosed, ErrConnectionReconnecting } from "./error";
|
|
9
|
+
import { ErrConnectionClosed, ErrConnectionReconnecting, ErrTransactionInProgress } from "./error";
|
|
10
10
|
import { nextTick } from "process";
|
|
11
11
|
import { authorizeSocket, createSocket, upgradeSocket } from "./protocol/socket-authorization";
|
|
12
12
|
import { ConnectionRequestBuffer } from "./protocol/connection-request-writer";
|
|
@@ -29,14 +29,36 @@ export class Connection {
|
|
|
29
29
|
_nextStatement() {
|
|
30
30
|
return `s-${this._stmtCounter++}`;
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
_logError(error) {
|
|
33
|
+
if (this.config.logLevel === 'error' || this.config.logLevel === 'notice' || this.config.logLevel === 'query') {
|
|
34
|
+
console.log(`\n\x1b[31m┌─ ERROR ────────────────────────────────────────\x1b[0m\n`
|
|
35
|
+
+ `\x1b[31m│\x1b[0m ${error}\n`
|
|
36
|
+
+ `\x1b[31m└────────────────────────────────────────────────\x1b[0m\n`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
_logQuery(text, args) {
|
|
40
|
+
if (this.config.logLevel === 'query') {
|
|
41
|
+
console.log(`\n\x1b[36m┌─ QUERY ─────────────────────────────────────────\x1b[0m\n`
|
|
42
|
+
+ `\x1b[36m│\x1b[0m ${text}\n`
|
|
43
|
+
+ `${args.length !== 0 ? `\x1b[36m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
44
|
+
+ `\x1b[36m└────────────────────────────────────────────────\x1b[0m`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
_logNotice(notice) {
|
|
48
|
+
if (this.config.logLevel === 'notice' || this.config.logLevel === 'query') {
|
|
49
|
+
console.log(`\n\x1b[33m┌─ NOTICE ───────────────────────────────────────\x1b[0m\n`
|
|
50
|
+
+ `\x1b[33m│\x1b[0m ${notice}\n`
|
|
51
|
+
+ `\x1b[33m└────────────────────────────────────────────────\x1b[0m\n`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
_registerSсhedule() {
|
|
33
55
|
if (!this._sheduled) {
|
|
34
56
|
this._sheduled = true;
|
|
35
57
|
this._writer.clear();
|
|
36
|
-
shedule[this.config.
|
|
58
|
+
shedule[this.config.syncSсhedule](() => this._sсhedule());
|
|
37
59
|
}
|
|
38
60
|
}
|
|
39
|
-
|
|
61
|
+
_sсhedule() {
|
|
40
62
|
if (this._reconnecting)
|
|
41
63
|
return;
|
|
42
64
|
this._writer.hasMore && this._socket.write(this._writer);
|
|
@@ -44,7 +66,7 @@ export class Connection {
|
|
|
44
66
|
this._sheduled = false;
|
|
45
67
|
}
|
|
46
68
|
_registerQuery(query) {
|
|
47
|
-
this.
|
|
69
|
+
this._registerSсhedule();
|
|
48
70
|
if (query instanceof ParseQuery) {
|
|
49
71
|
this._writer
|
|
50
72
|
.writeParse(query.meta.statement, query.text)
|
|
@@ -67,12 +89,12 @@ export class Connection {
|
|
|
67
89
|
this._writer = ConnectionRequestBuffer.new(65536);
|
|
68
90
|
this._sheduled = false;
|
|
69
91
|
this._queue = new Queue();
|
|
70
|
-
this._executingCounter = 0;
|
|
71
92
|
this._closing = null;
|
|
72
93
|
this._closed = false;
|
|
73
94
|
this._reconnecting = null;
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
95
|
+
this._inTransaction = false;
|
|
96
|
+
this._parsed = new Map();
|
|
97
|
+
this._parsing = new Map();
|
|
76
98
|
this._listeningCallbacks = new Map();
|
|
77
99
|
this._stmtCounter = 0;
|
|
78
100
|
this.config = config;
|
|
@@ -88,7 +110,7 @@ export class Connection {
|
|
|
88
110
|
logLevel: config.logLevel || 'error',
|
|
89
111
|
int8toBigint: config.int8toBigint || false,
|
|
90
112
|
queryTimeout: config.queryTimeout || 30000,
|
|
91
|
-
|
|
113
|
+
syncSсhedule: config.syncSсhedule || 'Immediate',
|
|
92
114
|
ssl: config.caPath ? 'require' : (config.ssl || 'prefer')
|
|
93
115
|
};
|
|
94
116
|
return createSocket(conf)
|
|
@@ -104,46 +126,52 @@ export class Connection {
|
|
|
104
126
|
* const users = await conn.query<User>`SELECT * FROM users WHERE id = ${1}`
|
|
105
127
|
*/
|
|
106
128
|
query(templates, ...params) {
|
|
107
|
-
if (this.isClosed)
|
|
129
|
+
if (this.isClosed) {
|
|
130
|
+
this._logError(ErrConnectionClosed);
|
|
108
131
|
return Future.reject(ErrConnectionClosed);
|
|
132
|
+
}
|
|
133
|
+
if (this._inTransaction) {
|
|
134
|
+
this._logError(ErrTransactionInProgress);
|
|
135
|
+
return Future.reject(ErrTransactionInProgress);
|
|
136
|
+
}
|
|
109
137
|
const { text, args } = compileSqlTemplate(templates, params);
|
|
110
138
|
const resolvers = Future.withResolvers();
|
|
111
|
-
if (this._reconnecting)
|
|
112
|
-
return this._reconnecting
|
|
139
|
+
if (this._reconnecting) {
|
|
140
|
+
return this._reconnecting
|
|
141
|
+
.tapErr(err => this._logError(err))
|
|
142
|
+
.andThen(() => this._performQuery(text, args, resolvers));
|
|
143
|
+
}
|
|
113
144
|
return this._performQuery(text, args, resolvers);
|
|
114
145
|
}
|
|
115
146
|
_performQuery(text, args, resolvers) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
+ `\x1b[36m│\x1b[0m ${text}\n`
|
|
119
|
-
+ `${args.length !== 0 ? `\x1b[36m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
120
|
-
+ `\x1b[36m└────────────────────────────────────────────────\x1b[0m`);
|
|
121
|
-
}
|
|
122
|
-
this._executingCounter++;
|
|
123
|
-
const parsed = this._parsed[text];
|
|
147
|
+
this._logQuery(text, args);
|
|
148
|
+
const parsed = this._parsed.get(text);
|
|
124
149
|
if (parsed) {
|
|
125
|
-
const query = new CollectQuery(
|
|
150
|
+
const query = new CollectQuery(text, args, parsed, resolvers, this.config.queryTimeout);
|
|
126
151
|
const err = this._registerQuery(query);
|
|
127
152
|
if (err) {
|
|
128
|
-
this._executingCounter--;
|
|
129
153
|
query.error(err);
|
|
130
|
-
|
|
154
|
+
this._logError(err);
|
|
131
155
|
}
|
|
132
156
|
return query.resolvers.future;
|
|
133
157
|
}
|
|
134
|
-
if (!this._parsing
|
|
135
|
-
const
|
|
158
|
+
if (!this._parsing.has(text)) {
|
|
159
|
+
const newMeta = {
|
|
160
|
+
statement: this._nextStatement(),
|
|
161
|
+
columns: EMPTY_ARRAY,
|
|
162
|
+
parameters: EMPTY_ARRAY
|
|
163
|
+
};
|
|
164
|
+
const parseQuery = new ParseQuery(text, newMeta, Future.withResolvers(), this.config.queryTimeout);
|
|
136
165
|
this._registerQuery(parseQuery);
|
|
137
|
-
this._parsing
|
|
166
|
+
this._parsing.set(text, parseQuery.resolvers.future);
|
|
138
167
|
}
|
|
139
|
-
const parsing = this._parsing
|
|
168
|
+
const parsing = this._parsing.get(text);
|
|
140
169
|
return parsing.andThen(meta => {
|
|
141
|
-
const query = new CollectQuery(
|
|
170
|
+
const query = new CollectQuery(text, args, meta, resolvers, this.config.queryTimeout);
|
|
142
171
|
const err = this._registerQuery(query);
|
|
143
172
|
if (err) {
|
|
144
|
-
this._executingCounter--;
|
|
145
173
|
query.error(err);
|
|
146
|
-
|
|
174
|
+
this._logError(err);
|
|
147
175
|
}
|
|
148
176
|
return query.resolvers.future;
|
|
149
177
|
});
|
|
@@ -155,46 +183,52 @@ export class Connection {
|
|
|
155
183
|
* await conn.execute`UPDATE users SET name = ${name} WHERE id = ${id}`
|
|
156
184
|
*/
|
|
157
185
|
execute(templates, ...params) {
|
|
158
|
-
if (this.isClosed)
|
|
186
|
+
if (this.isClosed) {
|
|
187
|
+
this._logError(ErrConnectionClosed);
|
|
159
188
|
return Future.reject(ErrConnectionClosed);
|
|
189
|
+
}
|
|
190
|
+
if (this._inTransaction) {
|
|
191
|
+
this._logError(ErrTransactionInProgress);
|
|
192
|
+
return Future.reject(ErrTransactionInProgress);
|
|
193
|
+
}
|
|
160
194
|
const { text, args } = compileSqlTemplate(templates, params);
|
|
161
195
|
const resolvers = Future.withResolvers();
|
|
162
|
-
if (this._reconnecting)
|
|
163
|
-
return this._reconnecting
|
|
196
|
+
if (this._reconnecting) {
|
|
197
|
+
return this._reconnecting
|
|
198
|
+
.tapErr(err => this._logError(err))
|
|
199
|
+
.andThen(() => this._performExecute(text, args, resolvers));
|
|
200
|
+
}
|
|
164
201
|
return this._performExecute(text, args, resolvers);
|
|
165
202
|
}
|
|
166
203
|
_performExecute(text, args, resolvers) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
+ `\x1b[35m│\x1b[0m ${text}\n`
|
|
170
|
-
+ `${args.length !== 0 ? `\x1b[35m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
171
|
-
+ `\x1b[35m└────────────────────────────────────────────────\x1b[0m`);
|
|
172
|
-
}
|
|
173
|
-
this._executingCounter++;
|
|
174
|
-
const parsed = this._parsed[text];
|
|
204
|
+
this._logQuery(text, args);
|
|
205
|
+
const parsed = this._parsed.get(text);
|
|
175
206
|
if (parsed) {
|
|
176
|
-
const query = new ExecuteQuery(
|
|
207
|
+
const query = new ExecuteQuery(text, args, parsed, resolvers, this.config.queryTimeout);
|
|
177
208
|
const err = this._registerQuery(query);
|
|
178
209
|
if (err) {
|
|
179
|
-
this._executingCounter--;
|
|
180
210
|
query.error(err);
|
|
181
|
-
|
|
211
|
+
this._logError(err);
|
|
182
212
|
}
|
|
183
213
|
return query.resolvers.future;
|
|
184
214
|
}
|
|
185
|
-
if (!this._parsing
|
|
186
|
-
const
|
|
215
|
+
if (!this._parsing.has(text)) {
|
|
216
|
+
const newMeta = {
|
|
217
|
+
statement: this._nextStatement(),
|
|
218
|
+
columns: EMPTY_ARRAY,
|
|
219
|
+
parameters: EMPTY_ARRAY
|
|
220
|
+
};
|
|
221
|
+
const parseQuery = new ParseQuery(text, newMeta, Future.withResolvers(), this.config.queryTimeout);
|
|
187
222
|
this._registerQuery(parseQuery);
|
|
188
|
-
this._parsing
|
|
223
|
+
this._parsing.set(text, parseQuery.resolvers.future);
|
|
189
224
|
}
|
|
190
|
-
const parsing = this._parsing
|
|
225
|
+
const parsing = this._parsing.get(text);
|
|
191
226
|
return parsing.andThen(meta => {
|
|
192
|
-
const query = new ExecuteQuery(
|
|
227
|
+
const query = new ExecuteQuery(text, args, meta, resolvers, this.config.queryTimeout);
|
|
193
228
|
const err = this._registerQuery(query);
|
|
194
229
|
if (err) {
|
|
195
|
-
this._executingCounter--;
|
|
196
230
|
query.error(err);
|
|
197
|
-
|
|
231
|
+
this._logError(err);
|
|
198
232
|
}
|
|
199
233
|
return query.resolvers.future;
|
|
200
234
|
});
|
|
@@ -207,8 +241,14 @@ export class Connection {
|
|
|
207
241
|
* for await (const row of conn.stream<User>`SELECT * FROM orders`) { ... }
|
|
208
242
|
*/
|
|
209
243
|
stream(templates, ...params) {
|
|
210
|
-
if (this.isClosed)
|
|
244
|
+
if (this.isClosed) {
|
|
245
|
+
this._logError(ErrConnectionClosed);
|
|
211
246
|
throw ErrConnectionClosed;
|
|
247
|
+
}
|
|
248
|
+
if (this._inTransaction) {
|
|
249
|
+
this._logError(ErrTransactionInProgress);
|
|
250
|
+
throw (ErrTransactionInProgress);
|
|
251
|
+
}
|
|
212
252
|
const { text, args } = compileSqlTemplate(templates, params);
|
|
213
253
|
let controller;
|
|
214
254
|
const stream = new ReadableStream({
|
|
@@ -219,43 +259,42 @@ export class Connection {
|
|
|
219
259
|
if (this._reconnecting) {
|
|
220
260
|
this._reconnecting
|
|
221
261
|
.tap(() => this._performStream(text, args, controller))
|
|
222
|
-
.tapErr(err =>
|
|
262
|
+
.tapErr(err => {
|
|
263
|
+
this._logError(err);
|
|
264
|
+
controller.error(err);
|
|
265
|
+
})
|
|
266
|
+
.recover();
|
|
223
267
|
return stream;
|
|
224
268
|
}
|
|
225
269
|
this._performStream(text, args, controller);
|
|
226
270
|
return stream;
|
|
227
271
|
}
|
|
228
272
|
_performStream(text, args, controller) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
+ `\x1b[34m│\x1b[0m ${text}\n`
|
|
232
|
-
+ `${args.length !== 0 ? `\x1b[34m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
233
|
-
+ `\x1b[34m└────────────────────────────────────────────────\x1b[0m`);
|
|
234
|
-
}
|
|
235
|
-
this._executingCounter++;
|
|
236
|
-
const parsed = this._parsed[text];
|
|
273
|
+
this._logQuery(text, args);
|
|
274
|
+
const parsed = this._parsed.get(text);
|
|
237
275
|
if (parsed) {
|
|
238
|
-
const query = new StreamQuery(
|
|
276
|
+
const query = new StreamQuery(text, args, parsed, controller, this.config.queryTimeout);
|
|
239
277
|
const err = this._registerQuery(query);
|
|
240
278
|
if (err) {
|
|
241
|
-
this._executingCounter--;
|
|
242
279
|
controller.error(err);
|
|
280
|
+
this._logError(err);
|
|
243
281
|
}
|
|
244
282
|
return;
|
|
245
283
|
}
|
|
246
|
-
if (!this._parsing
|
|
247
|
-
const
|
|
284
|
+
if (!this._parsing.has(text)) {
|
|
285
|
+
const newMeta = { statement: this._nextStatement(), columns: EMPTY_ARRAY, parameters: EMPTY_ARRAY };
|
|
286
|
+
const parseQuery = new ParseQuery(text, newMeta, Future.withResolvers(), this.config.queryTimeout);
|
|
248
287
|
this._registerQuery(parseQuery);
|
|
249
|
-
this._parsing
|
|
288
|
+
this._parsing.set(text, parseQuery.resolvers.future);
|
|
250
289
|
}
|
|
251
|
-
const parsing = this._parsing
|
|
290
|
+
const parsing = this._parsing.get(text);
|
|
252
291
|
parsing
|
|
253
292
|
.tap(meta => {
|
|
254
|
-
const query = new StreamQuery(
|
|
293
|
+
const query = new StreamQuery(text, args, meta, controller, this.config.queryTimeout);
|
|
255
294
|
const err = this._registerQuery(query);
|
|
256
295
|
if (err) {
|
|
257
|
-
this._executingCounter--;
|
|
258
296
|
controller.error(err);
|
|
297
|
+
this._logError(err);
|
|
259
298
|
}
|
|
260
299
|
})
|
|
261
300
|
.tapErr(err => {
|
|
@@ -272,13 +311,12 @@ export class Connection {
|
|
|
272
311
|
* })
|
|
273
312
|
*/
|
|
274
313
|
begin(txCallback) {
|
|
275
|
-
if (this.isClosed)
|
|
276
|
-
return Future.reject(ErrConnectionClosed);
|
|
277
314
|
return Begin()
|
|
278
315
|
.andThen(() => this.execute `begin`)
|
|
279
316
|
.andThen(() => {
|
|
317
|
+
this._inTransaction = true;
|
|
280
318
|
const tx = new Transaction(this);
|
|
281
|
-
return Future.of(txCallback(tx))
|
|
319
|
+
return Future.of(() => txCallback(tx))
|
|
282
320
|
.tap(() => {
|
|
283
321
|
if (tx.isActive)
|
|
284
322
|
return tx.commit();
|
|
@@ -287,29 +325,25 @@ export class Connection {
|
|
|
287
325
|
if (tx.isActive)
|
|
288
326
|
return tx.rollback();
|
|
289
327
|
});
|
|
290
|
-
})
|
|
328
|
+
})
|
|
329
|
+
.finally(() => this._inTransaction = false);
|
|
291
330
|
}
|
|
292
331
|
/** Sends a `pg_notify` message on `channelName` (payload ≤ 8000 bytes). */
|
|
293
332
|
notify(channelName, payload = "") {
|
|
294
|
-
|
|
295
|
-
return Future.reject(ErrConnectionClosed);
|
|
296
|
-
return this.execute `select pg_notify(${channelName}, ${payload})`.map(() => { });
|
|
333
|
+
return this.execute `select pg_notify(${channelName}, ${payload})`;
|
|
297
334
|
}
|
|
298
335
|
/** Subscribes `callback` to `channelName`, issuing `LISTEN` on first subscription. */
|
|
299
336
|
listen(channelName, callback) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return this.execute `listen ${sql.ident(channelName)};`;
|
|
337
|
+
return this.execute `listen ${sql.ident(channelName)};`
|
|
338
|
+
.tap(() => {
|
|
339
|
+
if (!this._listeningCallbacks.has(channelName)) {
|
|
340
|
+
this._listeningCallbacks.set(channelName, new Set());
|
|
341
|
+
}
|
|
342
|
+
this._listeningCallbacks.get(channelName).add(callback);
|
|
343
|
+
});
|
|
308
344
|
}
|
|
309
345
|
/** Unsubscribes `callback`, issuing `UNLISTEN` once no callbacks remain. */
|
|
310
346
|
unlisten(channelName, callback) {
|
|
311
|
-
if (this.isClosed)
|
|
312
|
-
return Future.reject(ErrConnectionClosed);
|
|
313
347
|
if (!this._listeningCallbacks.has(channelName)) {
|
|
314
348
|
return Ok();
|
|
315
349
|
}
|
|
@@ -317,7 +351,7 @@ export class Connection {
|
|
|
317
351
|
callbackSet.delete(callback);
|
|
318
352
|
if (callbackSet.size === 0) {
|
|
319
353
|
this._listeningCallbacks.delete(channelName);
|
|
320
|
-
return this.execute `unlisten ${sql.ident(channelName)}
|
|
354
|
+
return this.execute `unlisten ${sql.ident(channelName)};`;
|
|
321
355
|
}
|
|
322
356
|
return Ok();
|
|
323
357
|
}
|
|
@@ -337,10 +371,9 @@ export class Connection {
|
|
|
337
371
|
}
|
|
338
372
|
_performReconnect() {
|
|
339
373
|
this._socket.destroy();
|
|
340
|
-
this._parsed
|
|
341
|
-
this._parsing
|
|
374
|
+
this._parsed.clear();
|
|
375
|
+
this._parsing.clear();
|
|
342
376
|
this._sheduled = false;
|
|
343
|
-
this._executingCounter = 0;
|
|
344
377
|
while (this._queue.hasMore) {
|
|
345
378
|
this._queue.shift.error(ErrConnectionReconnecting);
|
|
346
379
|
}
|
|
@@ -382,16 +415,16 @@ export class Connection {
|
|
|
382
415
|
const query = this._currentQuery;
|
|
383
416
|
const columns = reader.readRowDescription();
|
|
384
417
|
query.meta.columns = columns;
|
|
385
|
-
|
|
386
|
-
this._parsed
|
|
418
|
+
this._parsing.delete(query.text);
|
|
419
|
+
this._parsed.set(query.text, query.meta);
|
|
387
420
|
query.complete();
|
|
388
421
|
}
|
|
389
422
|
break;
|
|
390
423
|
case ResponseTypes.NoData:
|
|
391
424
|
{
|
|
392
425
|
const query = this._currentQuery;
|
|
393
|
-
|
|
394
|
-
this._parsed
|
|
426
|
+
this._parsing.delete(query.text);
|
|
427
|
+
this._parsed.set(query.text, query.meta);
|
|
395
428
|
query.complete();
|
|
396
429
|
}
|
|
397
430
|
break;
|
|
@@ -410,40 +443,29 @@ export class Connection {
|
|
|
410
443
|
reader.skipBytes(length);
|
|
411
444
|
const query = this._currentQuery;
|
|
412
445
|
query.complete();
|
|
413
|
-
this._executingCounter--;
|
|
414
446
|
}
|
|
415
447
|
break;
|
|
416
448
|
case ResponseTypes.ErrorResponse:
|
|
417
449
|
{
|
|
418
450
|
const error = reader.readErrorResponse();
|
|
419
|
-
|
|
420
|
-
console.log(`\n\x1b[31m┌─ ERROR ────────────────────────────────────────\x1b[0m\n`
|
|
421
|
-
+ `\x1b[31m│\x1b[0m ${error}\n`
|
|
422
|
-
+ `\x1b[31m└────────────────────────────────────────────────\x1b[0m\n`);
|
|
423
|
-
}
|
|
451
|
+
this._logError(error);
|
|
424
452
|
const query = this._currentQuery;
|
|
425
|
-
if (
|
|
426
|
-
|
|
427
|
-
}
|
|
453
|
+
if (query instanceof ParseQuery)
|
|
454
|
+
this._parsing.delete(query.text);
|
|
428
455
|
query.error(error);
|
|
429
|
-
this._executingCounter--;
|
|
430
456
|
}
|
|
431
457
|
break;
|
|
432
458
|
case ResponseTypes.ReadyForQuery:
|
|
433
459
|
{
|
|
434
460
|
reader.skipBytes(length);
|
|
435
461
|
this._queue.next();
|
|
436
|
-
this.
|
|
462
|
+
this._tryFinishClosing();
|
|
437
463
|
}
|
|
438
464
|
break;
|
|
439
465
|
case ResponseTypes.Notice:
|
|
440
466
|
{
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
console.log(`\n\x1b[33m┌─ NOTICE ───────────────────────────────────────\x1b[0m\n`
|
|
444
|
-
+ `\x1b[33m│\x1b[0m ${message}\n`
|
|
445
|
-
+ `\x1b[33m└────────────────────────────────────────────────\x1b[0m\n`);
|
|
446
|
-
}
|
|
467
|
+
const notice = reader.readErrorResponse();
|
|
468
|
+
this._logNotice(notice);
|
|
447
469
|
}
|
|
448
470
|
break;
|
|
449
471
|
case ResponseTypes.NotificationResponse:
|
|
@@ -470,6 +492,19 @@ export class Connection {
|
|
|
470
492
|
get isClosed() {
|
|
471
493
|
return this._closed || !!this._closing;
|
|
472
494
|
}
|
|
495
|
+
_tryFinishClosing() {
|
|
496
|
+
if (!this._closing)
|
|
497
|
+
return;
|
|
498
|
+
if (this._queue.hasMore)
|
|
499
|
+
return;
|
|
500
|
+
setTimeout(() => {
|
|
501
|
+
if (!this._closing)
|
|
502
|
+
return;
|
|
503
|
+
if (!this._queue.hasMore) {
|
|
504
|
+
this._closing.resolve();
|
|
505
|
+
}
|
|
506
|
+
}, 0);
|
|
507
|
+
}
|
|
473
508
|
/**
|
|
474
509
|
* Closes the connection, awaiting for all pending queries. Not usable afterward.
|
|
475
510
|
*/
|
|
@@ -479,11 +514,6 @@ export class Connection {
|
|
|
479
514
|
if (this._closing) {
|
|
480
515
|
return this._closing.future;
|
|
481
516
|
}
|
|
482
|
-
if (!this._executingCounter) {
|
|
483
|
-
this._closed = true;
|
|
484
|
-
this._socket.destroy();
|
|
485
|
-
return Future.resolve();
|
|
486
|
-
}
|
|
487
517
|
const closing = Future.withResolvers();
|
|
488
518
|
this._closing = closing;
|
|
489
519
|
closing.future.tap(() => {
|
|
@@ -491,6 +521,7 @@ export class Connection {
|
|
|
491
521
|
this._closed = true;
|
|
492
522
|
this._socket.destroy();
|
|
493
523
|
});
|
|
524
|
+
this._tryFinishClosing();
|
|
494
525
|
return closing.future;
|
|
495
526
|
}
|
|
496
527
|
}
|
package/dist/error.d.ts
CHANGED
|
@@ -31,5 +31,6 @@ export declare const ErrSSLDenied: PostgresError;
|
|
|
31
31
|
export declare const ErrDatabaseNotFound: PostgresError;
|
|
32
32
|
export declare const ErrUntrustedCertificate: PostgresError;
|
|
33
33
|
export declare const ErrCertificateFileNotFound: PostgresError;
|
|
34
|
+
export declare const ErrTransactionInProgress: PostgresError;
|
|
34
35
|
export declare function createBindTypeError(index: number, expectedType: DataTypeOid, actualValue: unknown): PostgresError;
|
|
35
36
|
//# sourceMappingURL=error.d.ts.map
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,MAAM,sBAAsB,CAAA;AAGhE,qBAAa,aAAc,SAAQ,KAAK;IAEhB,OAAO,EAAE,MAAM;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;gBART,OAAO,EAAE,MAAM,EACxB,IAAI,GAAE,MAAqB,EAC3B,MAAM,GAAE,MAAW,EACnB,QAAQ,GAAE,MAAW,EACrB,KAAK,GAAE,MAAW,EAClB,IAAI,GAAE,MAAW,EACjB,QAAQ,GAAE,MAAW,EACrB,QAAQ,GAAE,MAAW,EACrB,UAAU,GAAE,MAAW;IAMlC,IAAI,YAAY,IAAI,OAAO,CAK1B;IAED,IAAI,WAAW,IAAI,OAAO,CAKzB;IAED,IAAI,uBAAuB,IAAI,OAAO,CAErC;IAED,IAAI,8BAA8B,IAAI,OAAO,CAE5C;IAED,IAAI,qBAAqB,IAAI,OAAO,CAEnC;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACJ;AAGD,eAAO,MAAM,gBAAgB,eAAmF,CAAA;AAChH,eAAO,MAAM,mBAAmB,eAAqE,CAAA;AACrG,eAAO,MAAM,yBAAyB,eAAiD,CAAA;AAEvF,eAAO,MAAM,eAAe,eAA8C,CAAA;AAE1E,eAAO,MAAM,aAAa,eAAkE,CAAA;AAE5F,eAAO,MAAM,oBAAoB,eAA6E,CAAA;AAE9G,eAAO,MAAM,mBAAmB,eAA8E,CAAA;AAC9G,eAAO,MAAM,yBAAyB,eAA2F,CAAA;AACjI,eAAO,MAAM,YAAY,eAA4D,CAAA;AACrF,eAAO,MAAM,mBAAmB,eAAwD,CAAA;AACxF,eAAO,MAAM,uBAAuB,eAA4E,CAAA;AAChH,eAAO,MAAM,0BAA0B,eAAkF,CAAA;AACzH,eAAO,MAAM,wBAAwB,eAGpC,CAAA;AA+BD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,GAAG,aAAa,CAqBjH"}
|
package/dist/error.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { handlers } from "./protocol/types";
|
|
1
2
|
export class PostgresError extends Error {
|
|
2
3
|
constructor(message, code = 'undeclared', detail = '', severity = '', where = '', hint = '', position = '', dataType = '', constraint = '') {
|
|
3
4
|
super(message);
|
|
@@ -51,14 +52,44 @@ export const ErrSSLDenied = new PostgresError("SSL is required but server denied
|
|
|
51
52
|
export const ErrDatabaseNotFound = new PostgresError('Database with that dsn not found');
|
|
52
53
|
export const ErrUntrustedCertificate = new PostgresError("Database SSL certificate is untrusted or self-signed");
|
|
53
54
|
export const ErrCertificateFileNotFound = new PostgresError("The SSL certificate file specified in caPath was not found");
|
|
55
|
+
export const ErrTransactionInProgress = new PostgresError("This connection has an active transaction — use the Transaction object passed into begin()'s callback instead of the Connection directly", 'transaction_in_progress', '', "ERROR");
|
|
56
|
+
function describeValue(value) {
|
|
57
|
+
if (value === null)
|
|
58
|
+
return 'null';
|
|
59
|
+
if (value === undefined)
|
|
60
|
+
return 'undefined';
|
|
61
|
+
if (typeof value === 'bigint')
|
|
62
|
+
return `${value}n`;
|
|
63
|
+
if (typeof value === 'string') {
|
|
64
|
+
return value.length > 60 ? `${JSON.stringify(value.slice(0, 60))}…` : JSON.stringify(value);
|
|
65
|
+
}
|
|
66
|
+
if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
67
|
+
return `Uint8Array(length=${value.length})`;
|
|
68
|
+
}
|
|
69
|
+
if (value instanceof Date) {
|
|
70
|
+
return `Date(${isNaN(value.getTime()) ? 'Invalid Date' : value.toISOString()})`;
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
const preview = value.slice(0, 5).map(describeValue).join(', ');
|
|
74
|
+
return `[${preview}${value.length > 5 ? ', …' : ''}] (length=${value.length})`;
|
|
75
|
+
}
|
|
76
|
+
if (typeof value === 'object') {
|
|
77
|
+
try {
|
|
78
|
+
const json = JSON.stringify(value);
|
|
79
|
+
return json.length > 120 ? `${json.slice(0, 120)}…` : json;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return Object.prototype.toString.call(value);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return String(value);
|
|
86
|
+
}
|
|
54
87
|
export function createBindTypeError(index, expectedType, actualValue) {
|
|
55
|
-
const position =
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
`
|
|
60
|
-
|
|
61
|
-
'writeBind() inside driver',
|
|
62
|
-
`Ensure that the argument passed as $${position} matches the PostgreSQL schema requirements.` // hint
|
|
63
|
-
);
|
|
88
|
+
const position = index + 1;
|
|
89
|
+
const info = handlers[expectedType];
|
|
90
|
+
const expectedPgType = info?.pgType ?? `oid ${expectedType}`;
|
|
91
|
+
const expectedJsShape = info?.jsShape ?? '(тип не описан в справочнике)';
|
|
92
|
+
const message = `Bind error: Parameter $${position} type mismatch. ` +
|
|
93
|
+
`Expected PostgreSQL type "${expectedPgType}" (${expectedJsShape}), received: ${describeValue(actualValue)}.`;
|
|
94
|
+
return new PostgresError(message, '22000', `Parameter $${position} failed client-side binary validation for pg type "${expectedPgType}".`, 'ERROR', 'writeBind() inside driver', `Pass a value matching ${expectedJsShape} for $${position}.`, '', expectedPgType);
|
|
64
95
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,35 @@ import { Pool as PgtxPool } from "./pool";
|
|
|
2
2
|
import { IdentifierClause, InsertClause, ArrayClause, UpdateClause, ExcludeUpdateClause, WhereClause, LiteralClause, FragmentClause } from './clauses';
|
|
3
3
|
import { Connection } from "./connection";
|
|
4
4
|
import { Transaction } from "./transaction";
|
|
5
|
+
export type PgPoint = {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
export type PgLine = {
|
|
10
|
+
a: number;
|
|
11
|
+
b: number;
|
|
12
|
+
c: number;
|
|
13
|
+
};
|
|
14
|
+
export type PgLineSegment = {
|
|
15
|
+
a: PgPoint;
|
|
16
|
+
b: PgPoint;
|
|
17
|
+
};
|
|
18
|
+
export type PgBox = {
|
|
19
|
+
high: PgPoint;
|
|
20
|
+
low: PgPoint;
|
|
21
|
+
};
|
|
22
|
+
export type PgPath = {
|
|
23
|
+
closed: boolean;
|
|
24
|
+
points: PgPoint[];
|
|
25
|
+
};
|
|
26
|
+
export type PgPolygon = {
|
|
27
|
+
points: PgPoint[];
|
|
28
|
+
};
|
|
29
|
+
export type PgInterval = {
|
|
30
|
+
months: number;
|
|
31
|
+
days: number;
|
|
32
|
+
microseconds: number;
|
|
33
|
+
};
|
|
5
34
|
/**
|
|
6
35
|
* Core SQL tagging utility for Pgtx.
|
|
7
36
|
* Provides type-safe helpers for building dynamic queries with recursive support.
|
|
@@ -16,7 +45,7 @@ export declare const sql: {
|
|
|
16
45
|
* // Result: (name, age) VALUES ($1, $2)
|
|
17
46
|
*
|
|
18
47
|
* @example
|
|
19
|
-
* sql.insert(
|
|
48
|
+
* sql.insert({ id: 1 }, { id: 2 })
|
|
20
49
|
* // Result: (id) VALUES ($1), ($2)
|
|
21
50
|
*/
|
|
22
51
|
insert: typeof InsertClause.create;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACX,aAAa,EACb,cAAc,EACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACX,aAAa,EACb,cAAc,EACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,MAAM,MAAM,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAC9C,MAAM,MAAM,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACxD,MAAM,MAAM,aAAa,GAAG;IAAE,CAAC,EAAE,OAAO,CAAC;IAAC,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AACtD,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAAA;AACnD,MAAM,MAAM,MAAM,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAA;AAC3D,MAAM,MAAM,SAAS,GAAG;IAAE,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAA;AAC7C,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/E;;;GAGG;AACH,eAAO,MAAM,GAAG;IACZ;;;;;;;;;;;OAWG;;IAGH;;;;;;OAMG;;IAGH;;;;;;OAMG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;KAWC;;IAGD;;;;;;;;;;OAUG;;IAGH;;;;;;;OAOG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;;;;;;;;;OAmBG;;CAEN,CAAA;AAGD;;;GAGG;AAEH,OAAO,EAAE,UAAU,IAAI,UAAU,EAAE,CAAA;AAEnC,OAAO,EAAE,WAAW,IAAI,WAAW,EAAE,CAAA;AAErC,OAAO,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAA;AAG3B,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/pool.d.ts
CHANGED
|
@@ -73,6 +73,8 @@ export declare class Pool {
|
|
|
73
73
|
get size(): number;
|
|
74
74
|
/** Total connections managed (idle + in use). */
|
|
75
75
|
get total(): number;
|
|
76
|
+
get isOpened(): boolean;
|
|
77
|
+
get isClosed(): boolean;
|
|
76
78
|
/**
|
|
77
79
|
* Closes idle connections and rejects pending `acquire()` calls. Not usable afterward.
|
|
78
80
|
*/
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAC;AAClD,OAAO,EAAiB,aAAa,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAc,iBAAiB,EAAE,GAAG,EAAU,MAAM,SAAS,CAAC;AAIrE;;;;;;;;GAQG;AACH,qBAAa,IAAI;IACb,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAO;gBAEZ,MAAM,EAAE,iBAAiB;IAOrC;;;OAGG;IACH,OAAO;IA2BP;;;;;OAKG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC;IAUnD,wFAAwF;IACxF,OAAO,CAAC,IAAI,EAAE,UAAU;IAoBxB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAU7D;;;;;OAKG;IACH,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;IAuBpE,qEAAqE;IACrE,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAuBzD;;;;;OAKG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;IAsC3F,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAQhD;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAY3D,kCAAkC;IAClC,IAAI,IAAI,WAEP;IAGD,iDAAiD;IACjD,IAAI,KAAK,WAER;IAGD;;OAEG;IACH,KAAK;CAiBR"}
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAC;AAClD,OAAO,EAAiB,aAAa,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAc,iBAAiB,EAAE,GAAG,EAAU,MAAM,SAAS,CAAC;AAIrE;;;;;;;;GAQG;AACH,qBAAa,IAAI;IACb,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAO;gBAEZ,MAAM,EAAE,iBAAiB;IAOrC;;;OAGG;IACH,OAAO;IA2BP;;;;;OAKG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC;IAUnD,wFAAwF;IACxF,OAAO,CAAC,IAAI,EAAE,UAAU;IAoBxB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAU7D;;;;;OAKG;IACH,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;IAuBpE,qEAAqE;IACrE,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAuBzD;;;;;OAKG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;IAsC3F,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAQhD;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAY3D,kCAAkC;IAClC,IAAI,IAAI,WAEP;IAGD,iDAAiD;IACjD,IAAI,KAAK,WAER;IAGD,IAAI,QAAQ,YAEX;IAGD,IAAI,QAAQ,YAEX;IAGD;;OAEG;IACH,KAAK;CAiBR"}
|