@qualithm/arrow-flight-sql-js 0.0.1

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 (49) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +433 -0
  3. package/dist/arrow.d.ts +65 -0
  4. package/dist/arrow.d.ts.map +1 -0
  5. package/dist/arrow.js +250 -0
  6. package/dist/arrow.js.map +1 -0
  7. package/dist/client.d.ts +416 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +1087 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/errors.d.ts +128 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +181 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/generated/index.d.ts +4 -0
  16. package/dist/generated/index.d.ts.map +1 -0
  17. package/dist/generated/index.js +33 -0
  18. package/dist/generated/index.js.map +1 -0
  19. package/dist/index.d.ts +40 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +43 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/metrics.d.ts +217 -0
  24. package/dist/metrics.d.ts.map +1 -0
  25. package/dist/metrics.js +304 -0
  26. package/dist/metrics.js.map +1 -0
  27. package/dist/pool.d.ts +161 -0
  28. package/dist/pool.d.ts.map +1 -0
  29. package/dist/pool.js +434 -0
  30. package/dist/pool.js.map +1 -0
  31. package/dist/proto.d.ts +168 -0
  32. package/dist/proto.d.ts.map +1 -0
  33. package/dist/proto.js +417 -0
  34. package/dist/proto.js.map +1 -0
  35. package/dist/query-builder.d.ts +1 -0
  36. package/dist/query-builder.d.ts.map +1 -0
  37. package/dist/query-builder.js +3 -0
  38. package/dist/query-builder.js.map +1 -0
  39. package/dist/retry.d.ts +92 -0
  40. package/dist/retry.d.ts.map +1 -0
  41. package/dist/retry.js +212 -0
  42. package/dist/retry.js.map +1 -0
  43. package/dist/types.d.ts +325 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +18 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +82 -0
  48. package/proto/Flight.proto +645 -0
  49. package/proto/FlightSql.proto +1925 -0
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Qualithm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
17
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,433 @@
1
+ # Arrow Flight SQL JS
2
+
3
+ Arrow Flight SQL client for JavaScript and TypeScript runtimes.
4
+
5
+ > 📦 **Package:** `@qualithm/arrow-flight-sql-js`
6
+ >
7
+ > 📚 **[API Documentation](https://qualithm.github.io/arrow-flight-sql-js/)**
8
+
9
+ ## Overview
10
+
11
+ This library provides a native JavaScript implementation for communicating with Arrow Flight SQL
12
+ servers. It handles the complete protocol stack:
13
+
14
+ - **gRPC/HTTP2 Transport** – Standards-based communication layer
15
+ - **Protocol Buffers** – Full Flight SQL message serialization
16
+ - **Connection Pooling** – Efficient connection reuse for high throughput
17
+ - **Arrow IPC Streaming** – Native Arrow record batch handling
18
+ - **Authentication** – Bearer tokens, basic auth, and custom handlers
19
+
20
+ ## Design Goals
21
+
22
+ Arrow Flight SQL JS is modeled on the canonical implementations:
23
+
24
+ | Reference | What We Adopt |
25
+ | ------------------------- | ---------------------------------------------------- |
26
+ | **Java** (reference impl) | Comprehensive API surface, error handling patterns |
27
+ | **C++** | Streaming-first patterns, performance considerations |
28
+ | **Go** | Connection pooling, context/cancellation model |
29
+
30
+ We aim for **API parity** with the official clients where JavaScript idioms allow.
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ # npm
36
+ npm install @qualithm/arrow-flight-sql-js
37
+
38
+ # bun
39
+ bun add @qualithm/arrow-flight-sql-js
40
+
41
+ # pnpm
42
+ pnpm add @qualithm/arrow-flight-sql-js
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```typescript
48
+ import { FlightSqlClient } from "@qualithm/arrow-flight-sql-js"
49
+
50
+ // Create a client
51
+ const client = new FlightSqlClient({
52
+ host: "localhost",
53
+ port: 31337,
54
+ tls: true,
55
+ token: "your-bearer-token"
56
+ })
57
+
58
+ // Execute a query
59
+ const stream = await client.execute("SELECT * FROM my_table LIMIT 100")
60
+
61
+ // Process Arrow record batches
62
+ for await (const batch of stream) {
63
+ console.log(`Received ${batch.numRows} rows`)
64
+ // batch is an Arrow RecordBatch
65
+ }
66
+
67
+ // Clean up
68
+ await client.close()
69
+ ```
70
+
71
+ ## Connection Pooling
72
+
73
+ ```typescript
74
+ import { FlightSqlPool } from "@qualithm/arrow-flight-sql-js"
75
+
76
+ const pool = new FlightSqlPool({
77
+ host: "localhost",
78
+ port: 31337,
79
+ // Pool configuration
80
+ minConnections: 2,
81
+ maxConnections: 10,
82
+ idleTimeoutMs: 30000
83
+ })
84
+
85
+ // Acquire a client from the pool
86
+ const client = await pool.acquire()
87
+ try {
88
+ const stream = await client.execute("SELECT 1")
89
+ // ... process results
90
+ } finally {
91
+ // Return to pool
92
+ pool.release(client)
93
+ }
94
+
95
+ // Or use the convenience method
96
+ const results = await pool.withClient(async (client) => {
97
+ return client.execute("SELECT * FROM users")
98
+ })
99
+
100
+ // Graceful shutdown
101
+ await pool.close()
102
+ ```
103
+
104
+ ## Observability & Metrics
105
+
106
+ Integrate with your observability stack using the metrics handler interface:
107
+
108
+ ```typescript
109
+ import {
110
+ FlightSqlClient,
111
+ ConsoleMetricsHandler,
112
+ InMemoryMetricsHandler,
113
+ MetricNames,
114
+ type MetricsHandler
115
+ } from "@qualithm/arrow-flight-sql-js"
116
+
117
+ // Console handler for development
118
+ const client = new FlightSqlClient({
119
+ host: "localhost",
120
+ port: 31337,
121
+ metrics: new ConsoleMetricsHandler()
122
+ })
123
+ // Output: [FlightSQL Metrics] ✓ query success (42ms)
124
+
125
+ // In-memory handler for testing
126
+ const metricsHandler = new InMemoryMetricsHandler()
127
+ const testClient = new FlightSqlClient({
128
+ host: "localhost",
129
+ port: 31337,
130
+ metrics: metricsHandler
131
+ })
132
+
133
+ // Query metrics after operations
134
+ await testClient.execute("SELECT 1")
135
+ console.log(metricsHandler.getAverageDuration("query"))
136
+ console.log(metricsHandler.getErrorRate("query"))
137
+ console.log(metricsHandler.getSummary())
138
+
139
+ // Custom handler for OpenTelemetry, Prometheus, etc.
140
+ class OpenTelemetryHandler implements MetricsHandler {
141
+ recordOperation(event) {
142
+ // Record to your tracing/metrics backend
143
+ tracer.startSpan(event.operation).end()
144
+ histogram.record(event.durationMs, { operation: event.operation })
145
+ }
146
+ recordGauge(event) {
147
+ /* ... */
148
+ }
149
+ recordCounter(event) {
150
+ /* ... */
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Standard Metric Names
156
+
157
+ Use `MetricNames` for consistent metric naming:
158
+
159
+ ```typescript
160
+ MetricNames.poolTotalConnections // "flight_sql.pool.total_connections"
161
+ MetricNames.poolActiveConnections // "flight_sql.pool.active_connections"
162
+ MetricNames.queriesExecuted // "flight_sql.queries.executed"
163
+ MetricNames.bytesReceived // "flight_sql.bytes.received"
164
+ MetricNames.retriesAttempted // "flight_sql.retries.attempted"
165
+ ```
166
+
167
+ ## Error Handling
168
+
169
+ The library provides a comprehensive error hierarchy:
170
+
171
+ ```typescript
172
+ import {
173
+ FlightSqlError, // Base error class
174
+ ConnectionError, // Network/connection issues
175
+ AuthenticationError, // Auth failures (401, 403)
176
+ QueryError, // SQL syntax or execution errors
177
+ TimeoutError, // Operation timeouts
178
+ ProtocolError, // Protocol/encoding issues
179
+ NotFoundError, // Resource not found
180
+ CancelledError // Operation cancelled
181
+ } from "@qualithm/arrow-flight-sql-js"
182
+
183
+ try {
184
+ await client.execute("SELECT * FROM missing_table")
185
+ } catch (error) {
186
+ if (error instanceof QueryError) {
187
+ console.error("SQL Error:", error.message)
188
+ console.error("SQL State:", error.sqlState)
189
+ } else if (error instanceof ConnectionError) {
190
+ console.error("Connection lost, will retry...")
191
+ } else if (error instanceof TimeoutError) {
192
+ console.error(`Operation timed out after ${error.timeoutMs}ms`)
193
+ }
194
+ }
195
+ ```
196
+
197
+ ## Retry Configuration
198
+
199
+ Configure automatic retries for transient failures:
200
+
201
+ ```typescript
202
+ import { FlightSqlClient, RetryPolicy, retryPolicies } from "@qualithm/arrow-flight-sql-js"
203
+
204
+ // Use pre-configured policies
205
+ const client = new FlightSqlClient({
206
+ host: "localhost",
207
+ port: 31337,
208
+ retry: retryPolicies.default // 3 retries, exponential backoff
209
+ })
210
+
211
+ // Available policies
212
+ retryPolicies.none // No retries
213
+ retryPolicies.fast // 3 retries, 50ms initial, 500ms max
214
+ retryPolicies.default // 3 retries, 100ms initial, 10s max
215
+ retryPolicies.aggressive // 5 retries, 200ms initial, 30s max
216
+ retryPolicies.reconnection // 10 retries, 1s initial, 60s max
217
+
218
+ // Custom retry configuration
219
+ const customPolicy = new RetryPolicy({
220
+ maxRetries: 5,
221
+ initialDelayMs: 100,
222
+ maxDelayMs: 5000,
223
+ backoffMultiplier: 2,
224
+ jitter: true, // Adds ±25% variance to prevent thundering herd
225
+ isRetryable: (error) => {
226
+ // Custom logic for which errors to retry
227
+ return error.code === 14 || error.message.includes("timeout")
228
+ }
229
+ })
230
+
231
+ const clientWithCustomRetry = new FlightSqlClient({
232
+ host: "localhost",
233
+ port: 31337,
234
+ retry: customPolicy
235
+ })
236
+ ```
237
+
238
+ ## Catalog Introspection
239
+
240
+ Explore database metadata with the catalog API:
241
+
242
+ ```typescript
243
+ // List all catalogs
244
+ const catalogs = await client.getCatalogs()
245
+ console.log("Catalogs:", catalogs)
246
+
247
+ // List schemas in a catalog
248
+ const schemas = await client.getSchemas("my_catalog", "public%")
249
+
250
+ // List tables with filtering
251
+ const tables = await client.getTables({
252
+ catalog: "my_catalog",
253
+ dbSchemaFilterPattern: "public",
254
+ tableNameFilterPattern: "user%",
255
+ tableTypes: ["TABLE", "VIEW"],
256
+ includeSchema: true // Include Arrow schema for each table
257
+ })
258
+
259
+ // Get table types supported by the server
260
+ const tableTypes = await client.getTableTypes()
261
+ // ["TABLE", "VIEW", "SYSTEM TABLE", "TEMPORARY TABLE", ...]
262
+
263
+ // Get primary key information
264
+ const primaryKeys = await client.getPrimaryKeys("users", "my_catalog", "public")
265
+ for (const pk of primaryKeys) {
266
+ console.log(`Column ${pk.columnName} at position ${pk.keySequence}`)
267
+ }
268
+
269
+ // Get foreign key relationships
270
+ const exportedKeys = await client.getExportedKeys("users") // Keys referencing this table
271
+ const importedKeys = await client.getImportedKeys("orders") // Keys this table references
272
+ ```
273
+
274
+ ## Prepared Statements
275
+
276
+ Use prepared statements for parameterized queries:
277
+
278
+ ```typescript
279
+ // Create a prepared statement
280
+ const stmt = await client.prepare("SELECT * FROM users WHERE id = ? AND status = ?")
281
+
282
+ try {
283
+ // Bind parameters and execute
284
+ const stream = await stmt.execute([userId, "active"])
285
+
286
+ for await (const batch of stream) {
287
+ console.log(`Received ${batch.numRows} rows`)
288
+ }
289
+
290
+ // Execute again with different parameters
291
+ const stream2 = await stmt.execute([otherUserId, "pending"])
292
+ // ...
293
+ } finally {
294
+ // Always close prepared statements
295
+ await stmt.close()
296
+ }
297
+ ```
298
+
299
+ ## API Reference
300
+
301
+ ### FlightSqlClient
302
+
303
+ The main client for interacting with Flight SQL servers.
304
+
305
+ #### Constructor Options
306
+
307
+ | Option | Type | Default | Description |
308
+ | ---------- | ------------------------ | ------- | ----------------------- |
309
+ | `host` | `string` | — | Server hostname |
310
+ | `port` | `number` | `443` | Server port |
311
+ | `tls` | `boolean` | `true` | Enable TLS |
312
+ | `token` | `string` | — | Bearer token for auth |
313
+ | `username` | `string` | — | Basic auth username |
314
+ | `password` | `string` | — | Basic auth password |
315
+ | `headers` | `Record<string, string>` | — | Custom metadata headers |
316
+ | `timeout` | `number` | `30000` | Request timeout in ms |
317
+
318
+ #### Methods
319
+
320
+ ##### Query Execution
321
+
322
+ - `execute(query: string, options?): AsyncIterable<RecordBatch>` – Execute SQL, stream results
323
+ - `executeUpdate(query: string): Promise<number>` – Execute DML, return affected rows
324
+ - `prepare(query: string): Promise<PreparedStatement>` – Create prepared statement
325
+
326
+ ##### Catalog Introspection
327
+
328
+ - `getCatalogs(): Promise<string[]>` – List available catalogs
329
+ - `getSchemas(catalog?, schemaPattern?): Promise<Schema[]>` – List schemas
330
+ - `getTables(options?): Promise<Table[]>` – List tables with filters
331
+ - `getTableTypes(): Promise<string[]>` – List table type names
332
+ - `getPrimaryKeys(table, catalog?, schema?): Promise<PrimaryKey[]>` – Get primary keys
333
+ - `getExportedKeys(table, catalog?, schema?): Promise<ForeignKey[]>` – Get exported foreign keys
334
+ - `getImportedKeys(table, catalog?, schema?): Promise<ForeignKey[]>` – Get imported foreign keys
335
+
336
+ ##### Low-Level Flight Operations
337
+
338
+ - `getFlightInfo(descriptor): Promise<FlightInfo>` – Get flight metadata
339
+ - `doGet(ticket): AsyncIterable<RecordBatch>` – Fetch data by ticket
340
+ - `doPut(descriptor, stream): Promise<void>` – Upload Arrow data
341
+ - `doAction(type, body?): AsyncIterable<Result>` – Execute custom action
342
+
343
+ ##### Connection Management
344
+
345
+ - `close(): Promise<void>` – Close connection
346
+ - `isConnected(): boolean` – Check connection status
347
+
348
+ ## Architecture
349
+
350
+ ```
351
+ ┌─────────────────────────────────────────────────────────┐
352
+ │ FlightSqlClient │
353
+ ├─────────────────────────────────────────────────────────┤
354
+ │ Query Builder │ Prepared Statements │ Catalog API │
355
+ ├─────────────────────────────────────────────────────────┤
356
+ │ Flight SQL Protocol │
357
+ │ (GetFlightInfo, DoGet, DoPut, DoAction) │
358
+ ├─────────────────────────────────────────────────────────┤
359
+ │ Protocol Buffers Layer │
360
+ │ (FlightDescriptor, FlightInfo, etc.) │
361
+ ├─────────────────────────────────────────────────────────┤
362
+ │ gRPC Transport │
363
+ │ (HTTP/2 + TLS + Auth Headers) │
364
+ ├─────────────────────────────────────────────────────────┤
365
+ │ Connection Pool │
366
+ │ (Health checks, reconnection, backoff) │
367
+ └─────────────────────────────────────────────────────────┘
368
+ ```
369
+
370
+ ## Compatibility
371
+
372
+ ### Runtime Support
373
+
374
+ | Runtime | Status | Notes |
375
+ | ------------------ | ------------ | ---------------------- |
376
+ | Node.js 20+ | ✅ Supported | Primary target |
377
+ | Bun | ✅ Supported | Development runtime |
378
+ | Deno | 🔄 Planned | Via npm compatibility |
379
+ | Cloudflare Workers | 🔄 Planned | Requires custom HTTP/2 |
380
+ | Browser | 🔄 Planned | Via gRPC-web proxy |
381
+
382
+ ### Flight SQL Servers
383
+
384
+ Tested against:
385
+
386
+ - Apache Arrow Flight SQL reference server
387
+ - DuckDB Flight SQL extension
388
+ - DataFusion Ballista
389
+ - Custom lakehouse implementations
390
+
391
+ ## Development
392
+
393
+ ```bash
394
+ # Install dependencies
395
+ bun install
396
+
397
+ # Run tests
398
+ bun test
399
+
400
+ # Run unit tests only
401
+ bun test:unit
402
+
403
+ # Run integration tests (requires Flight SQL server)
404
+ bun test:integration
405
+
406
+ # Lint and format
407
+ bun run lint:fix
408
+ bun run format:fix
409
+
410
+ # Generate API documentation
411
+ bun run docs
412
+ ```
413
+
414
+ ## Flight SQL Protocol Reference
415
+
416
+ This client implements the
417
+ [Arrow Flight SQL specification](https://arrow.apache.org/docs/format/FlightSql.html):
418
+
419
+ - **Flight SQL 13.0** – Current target version
420
+ - Full protobuf message support
421
+ - All standard actions (CreatePreparedStatement, ClosePreparedStatement, etc.)
422
+ - Catalog introspection commands
423
+ - Transaction support (where server supports it)
424
+
425
+ ## License
426
+
427
+ MIT
428
+
429
+ ## Related Projects
430
+
431
+ - [Apache Arrow](https://arrow.apache.org/) – The Arrow columnar format
432
+ - [Arrow Flight](https://arrow.apache.org/docs/format/Flight.html) – High-performance data transport
433
+ - [Arrow Flight SQL](https://arrow.apache.org/docs/format/FlightSql.html) – SQL over Flight
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Arrow IPC utilities for parsing Flight data
3
+ *
4
+ * Flight SQL transmits data in Arrow IPC format. This module provides
5
+ * utilities for parsing schemas and record batches from raw IPC bytes.
6
+ */
7
+ import { type RecordBatch, type Schema, Table } from "apache-arrow";
8
+ /**
9
+ * Parse an Arrow schema from IPC format bytes
10
+ *
11
+ * The schema bytes format from Flight:
12
+ * - 4 bytes: IPC_CONTINUATION_TOKEN (0xFFFFFFFF)
13
+ * - 4 bytes: message length
14
+ * - flatbuffer Message with Schema header
15
+ *
16
+ * Uses MessageReader to parse schema-only IPC messages, which is the correct
17
+ * approach for FlightInfo.schema bytes (as opposed to RecordBatchReader which
18
+ * expects a full IPC stream with record batches).
19
+ */
20
+ export declare function parseSchema(schemaBytes: Uint8Array): Schema;
21
+ /**
22
+ * Parse schema from FlightInfo response
23
+ * Returns null if schema is empty or cannot be parsed
24
+ */
25
+ export declare function tryParseSchema(schemaBytes: Uint8Array): Schema | null;
26
+ /**
27
+ * Parse a single FlightData message into a RecordBatch
28
+ *
29
+ * Flight sends data in a streaming format where:
30
+ * - First message: Schema (dataHeader only, no dataBody)
31
+ * - Subsequent messages: RecordBatch (dataHeader + dataBody)
32
+ *
33
+ * The dataHeader is a raw flatbuffer Message (without IPC framing).
34
+ * We need to frame it before passing to apache-arrow.
35
+ *
36
+ * @param dataHeader - IPC Message flatbuffer (without continuation/length prefix)
37
+ * @param dataBody - IPC Message body (raw data buffers)
38
+ * @param schema - Schema to use for parsing (from FlightInfo or first message)
39
+ */
40
+ export declare function parseFlightData(dataHeader: Uint8Array, dataBody: Uint8Array, schema: Schema): RecordBatch | null;
41
+ /**
42
+ * Async iterable that parses FlightData messages into RecordBatches
43
+ */
44
+ export declare function parseFlightDataStream(flightDataStream: AsyncIterable<{
45
+ dataHeader?: Uint8Array;
46
+ dataBody?: Uint8Array;
47
+ appMetadata?: Uint8Array;
48
+ }>, schema: Schema): AsyncGenerator<RecordBatch, void, unknown>;
49
+ /**
50
+ * Collect all record batches into a Table
51
+ */
52
+ export declare function collectToTable(batches: AsyncIterable<RecordBatch> | Iterable<RecordBatch>, schema: Schema): Promise<Table>;
53
+ /**
54
+ * Get column names from a schema
55
+ */
56
+ export declare function getColumnNames(schema: Schema): string[];
57
+ /**
58
+ * Get the number of rows in a table
59
+ */
60
+ export declare function getRowCount(table: Table): number;
61
+ /**
62
+ * Convert a Table to an array of plain objects
63
+ */
64
+ export declare function tableToObjects(table: Table): Record<string, unknown>[];
65
+ //# sourceMappingURL=arrow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrow.d.ts","sourceRoot":"","sources":["../src/arrow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,KAAK,WAAW,EAGhB,KAAK,MAAM,EACX,KAAK,EAEN,MAAM,cAAc,CAAA;AAMrB;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM,CAc3D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAUrE;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,MAAM,GACb,WAAW,GAAG,IAAI,CA+BpB;AAqFD;;GAEG;AACH,wBAAuB,qBAAqB,CAC1C,gBAAgB,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,EAAE,UAAU,CAAA;IACrB,WAAW,CAAC,EAAE,UAAU,CAAA;CACzB,CAAC,EACF,MAAM,EAAE,MAAM,GACb,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,CAgB5C;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,EAC3D,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,CAAC,CAwBhB;AAwBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEhD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CActE"}