@m2k-5f/pgtx 2.7.1 → 2.7.3

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.
Files changed (43) hide show
  1. package/README.md +48 -31
  2. package/dist/batch.d.ts +4 -1
  3. package/dist/batch.d.ts.map +1 -1
  4. package/dist/batch.js +14 -7
  5. package/dist/clauses/fragment.clause.js +1 -1
  6. package/dist/connection.d.ts +17 -16
  7. package/dist/connection.d.ts.map +1 -1
  8. package/dist/connection.js +182 -166
  9. package/dist/error.d.ts +4 -1
  10. package/dist/error.d.ts.map +1 -1
  11. package/dist/error.js +15 -7
  12. package/dist/pool.d.ts +1 -1
  13. package/dist/pool.d.ts.map +1 -1
  14. package/dist/pool.js +5 -3
  15. package/dist/protocol/connection-request-writer.d.ts +24 -11
  16. package/dist/protocol/connection-request-writer.d.ts.map +1 -1
  17. package/dist/protocol/connection-request-writer.js +217 -47
  18. package/dist/protocol/connection-response-reader.d.ts +5 -15
  19. package/dist/protocol/connection-response-reader.d.ts.map +1 -1
  20. package/dist/protocol/connection-response-reader.js +116 -76
  21. package/dist/protocol/constants.d.ts +37 -30
  22. package/dist/protocol/constants.d.ts.map +1 -1
  23. package/dist/protocol/constants.js +35 -29
  24. package/dist/protocol/socket-authorization.d.ts.map +1 -1
  25. package/dist/protocol/socket-authorization.js +7 -7
  26. package/dist/protocol/socket-connector.d.ts +4 -4
  27. package/dist/protocol/socket-connector.d.ts.map +1 -1
  28. package/dist/protocol/socket-connector.js +2 -2
  29. package/dist/query.d.ts +16 -20
  30. package/dist/query.d.ts.map +1 -1
  31. package/dist/query.js +15 -22
  32. package/dist/queue.d.ts +1 -0
  33. package/dist/queue.d.ts.map +1 -1
  34. package/dist/queue.js +1 -0
  35. package/dist/types.d.ts +3 -1
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/utils/template-compiler.d.ts +5 -2
  38. package/dist/utils/template-compiler.d.ts.map +1 -1
  39. package/dist/utils/template-compiler.js +4 -1
  40. package/dist/utils.d.ts +8 -0
  41. package/dist/utils.d.ts.map +1 -0
  42. package/dist/utils.js +73 -0
  43. package/package.json +2 -2
package/README.md CHANGED
@@ -3,9 +3,7 @@
3
3
  [![Tests](https://github.com/M2K-5F/pgtx/actions/workflows/tests.yaml/badge.svg)](https://github.com/M2K-5F/pgtx/actions/workflows/tests.yaml)
4
4
  [![npm version](https://img.shields.io/npm/v/@m2k-5f/pgtx.svg)](https://www.npmjs.com/package/@m2k-5f/pgtx)
5
5
 
6
- A PostgreSQL driver for Node.js that pipelines everything by default, caches prepared statements without asking, and doesn't ship a single dependency.
7
-
8
- It exists because `pg` leaves throughput on the table and `postgres.js`, while fast, still isn't fast enough once you actually saturate a connection pool. Pgtx is built around one idea: batch what can be batched, write to the socket once, and get out of the way.
6
+ A PostgreSQL driver for Node.js with an API that doesn't require a manual to use. Built for regular applications, not for people who need four different flavors of the same stream implementation or a config object with forty optional fields you'll never touch.
9
7
 
10
8
  ```bash
11
9
  npm install @m2k-5f/pgtx
@@ -25,8 +23,9 @@ const pool = new Pool({
25
23
 
26
24
  const [user] = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
27
25
 
26
+ // returns rows → query, doesn't → execute
28
27
  await pool.execute`
29
- INSERT INTO users ${sql.insert([{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }])}
28
+ INSERT INTO users ${sql.insert<User>([{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }])}
30
29
  `
31
30
 
32
31
  await pool.begin(async tx => {
@@ -43,18 +42,34 @@ Benchmarks run on GitHub Actions (Ubuntu, 2 vCPUs), reproducible, sources in thi
43
42
 
44
43
  **HTTP throughput against `postgres.js` and Bun's own native `Bun.sql` driver, on Bun:**
45
44
 
46
- | Connections | Pgtx | Postgres.js | Bun.sql | vs Postgres.js | vs Bun.sql |
47
- |---:|---:|---:|---:|---:|---:|
48
- | 50 | **27,885 req/s** | 8,967 req/s | 10,170 req/s | 3.11× | 2.74× |
49
- | 200 | **31,975 req/s** | 9,861 req/s | 11,725 req/s | 3.24× | 2.73× |
50
- | 500 | **31,245 req/s** | 8,289 req/s | 11,005 req/s | 3.77× | 2.84× |
45
+ | Connections | Pgtx | Postgres.js | Bun.sql |
46
+ |---:|---:|---:|---:|
47
+ | 50 | **21,093 req/s** | 8,967 req/s | 10,170 req/s |
48
+ | 200 | **22,731 req/s** | 9,861 req/s | 11,725 req/s |
49
+ | 500 | **22,673 req/s** | 8,289 req/s | 11,005 req/s |
51
50
 
52
- Bun.sql is Bun's own built-in driver, written in native code and generally treated as the speed baseline in that ecosystem. Pgtx stays 2.7-2.8× ahead of it at every concurrency level tested — the gap doesn't come from JS-vs-native, it comes from the protocol.
51
+ Bun.sql is Bun's own built-in driver, written in native code and generally treated as the speed baseline in that ecosystem. Pgtx stays ahead of it at every concurrency level tested — the gap doesn't come from JS-vs-native, it comes from the protocol implementation.
53
52
 
54
53
  **How:** everything you fire concurrently against the same connection gets folded into one pipelined write — Parse/Bind/Execute for every query in the batch goes out in a single `socket.write()`, and results get demuxed as they come back, in order, without buffering rows you haven't asked for yet. Prepared statements are cached and deduplicated automatically, row descriptions are cached alongside them, and the binary protocol skips text (de)serialization where it can. None of this requires you to change how you write queries.
55
54
 
56
55
  ## The parts worth knowing about
57
56
 
57
+
58
+ ### Every query is its own commit boundary
59
+
60
+ Fire off several queries in the same batch and one of them fails — the others aren't affected. Each query gets its own Sync, which means its own implicit transaction: an error in query B doesn't undo query A, even if A already returned and B is still in flight on the same pipelined write.
61
+
62
+ ```typescript
63
+ const [a, b] = await Promise.allSettled([
64
+ pool.execute`UPDATE accounts SET balance = balance + 100 WHERE id = ${1}`,
65
+ pool.execute`INSERT INTO accounts (id) VALUES (${1})` // duplicate key, fails
66
+ ])
67
+ // a: fulfilled, the balance update is committed regardless of b's outcome
68
+ ```
69
+
70
+ This isolation is per-statement, not free-standing atomicity across statements — if you need several queries to succeed or fail together, that's what `begin()` and `savepoint()` are for. Outside a transaction, every query stands on its own.
71
+
72
+
58
73
  ### Errors you can pattern-match on
59
74
 
60
75
  Every call returns a `Future<T[], PostgresError>` from [fluent-future](https://www.npmjs.com/package/fluent-future) instead of a bare `Promise`. `await` still works exactly like you'd expect — but you also get typed errors and a way to handle them without a `try/catch` pyramid:
@@ -66,9 +81,24 @@ const users = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
66
81
  .tapErr(err => logger.error(err))
67
82
  ```
68
83
 
84
+
85
+ ### Transactions and savepoints
86
+
87
+ ```typescript
88
+ await pool.begin(async tx => {
89
+ await tx.execute`INSERT INTO orders (user_id) VALUES (${userId})`
90
+
91
+ await tx.savepoint('reserve_stock', async stx => {
92
+ await stx.execute`UPDATE stock SET count = count - 1 WHERE product_id = ${productId}`
93
+ if (outOfStock) throw new Error('out of stock') // only the savepoint rolls back
94
+ }).tapErr(console.log)
95
+ })
96
+ ```
97
+
98
+
69
99
  ### Pipelining is automatic, not opt-in
70
100
 
71
- `Bind`/`.bind` from fluent-future group independent queries into the same pipeline batch for you:
101
+ `Bind`/`.bind` from [fluent-future](https://www.npmjs.com/package/fluent-future) group independent queries into the same pipeline batch for you:
72
102
 
73
103
  ```typescript
74
104
  // 5 queries, 2 round-trips
@@ -94,29 +124,16 @@ for await (const log of pool.stream<Log>`SELECT * FROM application_logs WHERE le
94
124
  }
95
125
  ```
96
126
 
127
+
97
128
  It's a real Web Streams object, so it drops straight into an HTTP response body:
98
129
 
99
130
  ```typescript
100
- export default {
101
- async fetch(req) {
102
- const stream = pool.stream`SELECT id, email FROM giant_user_table`
103
- return new Response(stream, { headers: { "Content-Type": "application/json" } })
104
- }
131
+ fetch(req) {
132
+ const stream = pool.stream`SELECT id, email FROM giant_user_table`
133
+ return new Response(stream, { headers: { "Content-Type": "application/json" } })
105
134
  }
106
135
  ```
107
136
 
108
- ### Transactions and savepoints
109
-
110
- ```typescript
111
- await pool.begin(async tx => {
112
- await tx.execute`INSERT INTO orders (user_id) VALUES (${userId})`
113
-
114
- await tx.savepoint('reserve_stock', async stx => {
115
- await stx.execute`UPDATE stock SET count = count - 1 WHERE product_id = ${productId}`
116
- if (outOfStock) throw new Error('out of stock') // only the savepoint rolls back
117
- }).tapErr(console.log)
118
- })
119
- ```
120
137
 
121
138
  ### LISTEN / NOTIFY without babysitting a connection
122
139
 
@@ -199,10 +216,10 @@ interface ConnectionPartialConfig {
199
216
  host: string
200
217
  port: number
201
218
  database: string
202
- logLevel?: 'error' | 'notice' | 'query' // default 'error'
219
+ logLevel?: 'error' | 'notice' | 'query' | "none" // default 'error'
203
220
  int8toBigint?: boolean // default false
204
- queryTimeout?: number // default 30000
205
- syncShedule?: 'beforeMicrotask' | 'afterMicrotask' | 'Immediate' // default 'afterMicrotask'
221
+ queryTimeout?: number // default 30000 (ms)
222
+ syncShedule?: 'beforeMicrotask' | 'afterMicrotask' | 'Immediate' // default 'Immediate'
206
223
  ssl?: 'disable' | 'prefer' | 'require' // defaut 'prefer'
207
224
  caPath?: string // forces `ssl` to 'require' if provided
208
225
  }
package/dist/batch.d.ts CHANGED
@@ -7,9 +7,12 @@ export declare class Batch {
7
7
  constructor(buffer: ConnectionRequestWriter);
8
8
  registerParse(query: PostgresQuery): void;
9
9
  registerQuery(query: PostgresQuery): void;
10
+ get hasMore(): boolean;
10
11
  end(): ConnectionRequestWriter;
11
12
  get current(): PostgresQuery;
12
13
  next(): void;
13
- reject(cause: PostgresError): number;
14
+ get shift(): PostgresQuery;
15
+ error(cause: PostgresError): void;
16
+ get residual(): PostgresQuery[];
14
17
  }
15
18
  //# sourceMappingURL=batch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,qBAAa,KAAK;IACd,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,OAAO,CAAyB;gBAE5B,MAAM,EAAE,uBAAuB;IAM3C,aAAa,CAAC,KAAK,EAAE,aAAa;IAOlC,aAAa,CAAC,KAAK,EAAE,aAAa;IAQlC,GAAG;IAIH,IAAI,OAAO,kBAEV;IAED,IAAI;IAIJ,MAAM,CAAC,KAAK,EAAE,aAAa;CAS9B"}
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,qBAAa,KAAK;IACd,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,OAAO,CAAyB;gBAE5B,MAAM,EAAE,uBAAuB;IAM3C,aAAa,CAAC,KAAK,EAAE,aAAa;IAOlC,aAAa,CAAC,KAAK,EAAE,aAAa;IASlC,IAAI,OAAO,YAEV;IAED,GAAG;IAIH,IAAI,OAAO,kBAEV;IAED,IAAI;IAIJ,IAAI,KAAK,kBAER;IAED,KAAK,CAAC,KAAK,EAAE,aAAa;IAM1B,IAAI,QAAQ,oBAEX;CACJ"}
package/dist/batch.js CHANGED
@@ -13,10 +13,14 @@ export class Batch {
13
13
  this._queryQueue.push(query);
14
14
  this._buffer
15
15
  .writeBind("", query.statement, query.args)
16
- .writeExecute("");
16
+ .writeExecute("")
17
+ .writeSync();
18
+ }
19
+ get hasMore() {
20
+ return this._queryQueue.hasMore;
17
21
  }
18
22
  end() {
19
- return this._buffer.writeSync();
23
+ return this._buffer;
20
24
  }
21
25
  get current() {
22
26
  return this._queryQueue.current;
@@ -24,12 +28,15 @@ export class Batch {
24
28
  next() {
25
29
  this._queryQueue.next();
26
30
  }
27
- reject(cause) {
28
- let counter = 0;
31
+ get shift() {
32
+ return this._queryQueue.shift;
33
+ }
34
+ error(cause) {
29
35
  while (this._queryQueue.hasMore) {
30
- counter++;
31
- this._queryQueue.shift.reject(cause);
36
+ this._queryQueue.shift.error(cause);
32
37
  }
33
- return counter;
38
+ }
39
+ get residual() {
40
+ return this._queryQueue.residual;
34
41
  }
35
42
  }
@@ -1,5 +1,5 @@
1
1
  import { Clause, } from "./abstract.clause";
2
- import { compileSqlTemplate } from "../utils/template-compiler";
2
+ import { compileSqlTemplate } from "../utils";
3
3
  export class FragmentClause extends Clause {
4
4
  constructor(templates, args) {
5
5
  super();
@@ -14,26 +14,28 @@ import { PostgresError } from "./error";
14
14
  */
15
15
  export declare class Connection {
16
16
  private readonly config;
17
- private _activeBatch;
17
+ private _writer;
18
+ private _sheduled;
19
+ private _queue;
18
20
  private _closing;
19
21
  private _closed;
20
22
  private _reconnecting;
21
- private _cachedBuffer;
22
23
  private _socket;
23
- private _batchQueue;
24
24
  private _parsed;
25
25
  private _parsing;
26
26
  private _listeningCallbacks;
27
27
  private _stmtCounter;
28
28
  private _nextStatement;
29
+ private _registerShedule;
30
+ private _shedule;
31
+ private _parseQuery;
32
+ private _registerQuery;
29
33
  private constructor();
30
34
  /**
31
35
  * Opens a new connection and authenticates.
32
36
  * @throws {PostgresError} if authentication fails or the connection can't be established
33
37
  */
34
38
  static new(config: ConnectionPartialConfig): Future<Connection, PostgresError>;
35
- private _registerBatch;
36
- private _sync;
37
39
  /**
38
40
  * Runs a query, binding template values as `$1, $2, ...`.
39
41
  * Parameterized queries are cached as prepared statements.
@@ -51,6 +53,15 @@ export declare class Connection {
51
53
  */
52
54
  execute(templates: TemplateStringsArray, ...params: any[]): Future<void, PostgresError>;
53
55
  private _performExecute;
56
+ /**
57
+ * Streams query results as a `ReadableStream`, without buffering rows in memory.
58
+ * Ideal for large result sets or piping straight into an HTTP response.
59
+ *
60
+ * @example
61
+ * for await (const row of conn.stream<User>`SELECT * FROM orders`) { ... }
62
+ */
63
+ stream<T extends Row>(templates: TemplateStringsArray, ...params: any[]): ReadableStream<T>;
64
+ private _performStream;
54
65
  /**
55
66
  * Runs `txCallback` inside `BEGIN`/`COMMIT`, rolling back on error.
56
67
  *
@@ -66,21 +77,11 @@ export declare class Connection {
66
77
  listen(channelName: string, callback: (payload: string) => void): Future<void, PostgresError>;
67
78
  /** Unsubscribes `callback`, issuing `UNLISTEN` once no callbacks remain. */
68
79
  unlisten(channelName: string, callback: (payload: string) => void): Future<void, PostgresError>;
69
- /**
70
- * Streams query results as a `ReadableStream`, without buffering rows in memory.
71
- * Ideal for large result sets or piping straight into an HTTP response.
72
- *
73
- * @example
74
- * for await (const row of conn.stream<User>`SELECT * FROM orders`) { ... }
75
- */
76
- stream<T extends Row>(templates: TemplateStringsArray, ...params: any[]): ReadableStream<T>;
77
- private _performStream;
78
80
  private _reconnect;
79
81
  private _performReconnect;
80
82
  private _restoreSubscriptions;
81
- private _getCurrentQuery;
83
+ private get _currentQuery();
82
84
  private _handlePacket;
83
- private get _hasQueries();
84
85
  /** Whether the connection is alive and usable. */
85
86
  get isOpened(): boolean;
86
87
  /** Whether the connection is closed or closing. */
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,uBAAuB,EAAmC,GAAG,EAAiB,MAAM,SAAS,CAAA;AACrI,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAA;AACjD,OAAO,EAAkD,aAAa,EAAE,MAAM,SAAS,CAAA;AAcvF;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAsD;IACtE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,aAAa,CAAgC;IAErD,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,WAAW,CAA4B;IAE/C,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,QAAQ,CAAsC;IAEtD,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,YAAY,CAAI;IAGxB,OAAO,CAAC,cAAc;IAKtB,OAAO;IAYP;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB;IAkB1C,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,KAAK;IASb;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAStE,OAAO,CAAC,aAAa;IA4CrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IASzD,OAAO,CAAC,eAAe;IAsCvB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAoB7D,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAOhD,sFAAsF;IACtF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAe/D,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;IAoB/F;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAyBvE,OAAO,CAAC,cAAc;IA2CtB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,aAAa;IAoIrB,OAAO,KAAK,WAAW,GAEtB;IAGD,kDAAkD;IAClD,IAAI,QAAQ,YAEX;IAGD,mDAAmD;IACnD,IAAI,QAAQ,YAEX;IAGD;;OAEG;IACH,KAAK;CAwBR"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,uBAAuB,EAAuC,GAAG,EAAiB,MAAM,SAAS,CAAA;AACzI,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAA;AACjD,OAAO,EAAkD,aAAa,EAAE,MAAM,SAAS,CAAA;AAevF;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,MAAM,CAA6B;IAE3C,OAAO,CAAC,QAAQ,CAAsD;IACtE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAA2C;IAEhE,OAAO,CAAC,OAAO,CAAiB;IAEhC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,QAAQ,CAAuC;IAEvD,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,YAAY,CAAI;IAExB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,cAAc;IAYtB,OAAO;IAYP;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB;IAkB1C;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAatE,OAAO,CAAC,aAAa;IA4CrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAazD,OAAO,CAAC,eAAe;IA2CvB;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IA2BvE,OAAO,CAAC,cAAc;IA8CtB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAoB7D,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAOhD,sFAAsF;IACtF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAe/D,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;IAoB/F,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,KAAK,aAAa,GAExB;IAGD,OAAO,CAAC,aAAa;IAgIrB,kDAAkD;IAClD,IAAI,QAAQ,YAEX;IAGD,mDAAmD;IACnD,IAAI,QAAQ,YAEX;IAGD;;OAEG;IACH,KAAK;CAwBR"}