@qualithm/arrow-flight-sql-js 0.4.0 → 0.4.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 (2) hide show
  1. package/README.md +17 -271
  2. package/package.json +5 -2
package/README.md CHANGED
@@ -17,18 +17,6 @@ servers. It handles the complete protocol stack:
17
17
  - **Arrow IPC Streaming** – Native Arrow record batch handling
18
18
  - **Authentication** – Bearer tokens, basic auth, and custom handlers
19
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
20
  ## Installation
33
21
 
34
22
  ```bash
@@ -185,86 +173,6 @@ for await (const batch of result.stream()) {
185
173
  | Export to file | Stream and write chunks |
186
174
  | Memory-constrained environment | Always `stream()`, never `collect()` unbounded results |
187
175
 
188
- ## Real-Time Subscriptions
189
-
190
- Subscribe to live data updates using the `DoExchange` bidirectional streaming protocol:
191
-
192
- ```typescript
193
- import { FlightSqlClient, SubscriptionMode } from "@qualithm/arrow-flight-sql-js"
194
-
195
- const client = new FlightSqlClient({
196
- host: "localhost",
197
- port: 31337,
198
- tls: true,
199
- auth: { type: "bearer", token: "your-bearer-token" }
200
- })
201
-
202
- await client.connect()
203
-
204
- // Subscribe to real-time updates
205
- const subscription = client.subscribe("SELECT * FROM events WHERE status = 'pending'", {
206
- mode: SubscriptionMode.ChangesOnly, // Full | ChangesOnly | Tail
207
- heartbeatMs: 30_000 // Server heartbeat interval
208
- })
209
-
210
- // Consume batches as they arrive
211
- for await (const batch of subscription) {
212
- console.log(`Received ${batch.numRows} rows`)
213
- }
214
-
215
- // Or with cancellation
216
- const controller = new AbortController()
217
- const cancelableSubscription = client.subscribe(query, {
218
- signal: controller.signal,
219
- autoReconnect: true,
220
- maxReconnectAttempts: 10
221
- })
222
-
223
- // Later: cancel the subscription
224
- controller.abort()
225
-
226
- // Or manually unsubscribe
227
- await cancelableSubscription.unsubscribe()
228
- ```
229
-
230
- ### Subscription Options
231
-
232
- | Option | Default | Description |
233
- | ---------------------- | ------------- | -------------------------------------------------- |
234
- | `mode` | `ChangesOnly` | Subscription mode (Full, ChangesOnly, Tail) |
235
- | `heartbeatMs` | `30000` | Server heartbeat interval in milliseconds |
236
- | `signal` | - | AbortSignal for cancellation |
237
- | `autoReconnect` | `true` | Auto-reconnect on connection loss |
238
- | `maxReconnectAttempts` | `10` | Maximum reconnection attempts |
239
- | `reconnectDelayMs` | `1000` | Initial reconnect delay |
240
- | `maxReconnectDelayMs` | `30000` | Maximum reconnect delay (with exponential backoff) |
241
-
242
- ### Low-Level DoExchange
243
-
244
- For custom bidirectional protocols:
245
-
246
- ```typescript
247
- const exchange = client.doExchange({
248
- type: DescriptorType.CMD,
249
- cmd: new TextEncoder().encode("CUSTOM_COMMAND")
250
- })
251
-
252
- // Send data to server
253
- await exchange.send({
254
- dataHeader: new Uint8Array(),
255
- dataBody: new Uint8Array(),
256
- appMetadata: new TextEncoder().encode(JSON.stringify({ action: "subscribe" }))
257
- })
258
-
259
- // Receive data from server
260
- for await (const data of exchange) {
261
- console.log("Received:", data)
262
- }
263
-
264
- // Half-close (signal end of client stream)
265
- await exchange.end()
266
- ```
267
-
268
176
  ## Observability & Metrics
269
177
 
270
178
  Integrate with your observability stack using the metrics handler interface:
@@ -490,90 +398,30 @@ try {
490
398
  }
491
399
  ```
492
400
 
493
- ## API Reference
494
-
495
- ### FlightSqlClient
496
-
497
- The main client for interacting with Flight SQL servers.
498
-
499
- #### Constructor Options
401
+ ## Real-Time Subscriptions
500
402
 
501
- | Option | Type | Default | Description |
502
- | ------------------ | ------------------------ | ------- | ------------------------------- |
503
- | `host` | `string` | — | Server hostname |
504
- | `port` | `number` | — | Server port |
505
- | `tls` | `boolean` | `true` | Enable TLS |
506
- | `auth` | `AuthConfig` | — | Authentication configuration |
507
- | `credentials` | `ChannelCredentials` | — | Custom gRPC channel credentials |
508
- | `metadata` | `Record<string, string>` | — | Custom metadata headers |
509
- | `connectTimeoutMs` | `number` | `30000` | Connection timeout in ms |
510
- | `requestTimeoutMs` | `number` | `60000` | Request timeout in ms |
403
+ > **Note:** Requires server support. Not all Flight SQL servers implement `DoExchange`.
511
404
 
512
- ##### AuthConfig
405
+ Subscribe to live data updates:
513
406
 
514
407
  ```typescript
515
- type AuthConfig =
516
- | { type: "bearer"; token: string }
517
- | { type: "basic"; username: string; password: string }
518
- | { type: "none" }
519
- ```
520
-
521
- #### Methods
522
-
523
- ##### Query Execution
524
-
525
- - `query(query: string, options?): Promise<QueryResult>` – Execute SQL, returns result with
526
- `stream()` and `collect()` methods
527
- - `execute(query: string, options?): Promise<FlightInfo>` – _(deprecated)_ Execute SQL, return
528
- flight info
529
- - `executeUpdate(query: string): Promise<bigint>` – Execute DML, return affected rows
530
- - `prepare(query: string): Promise<PreparedStatement>` – Create prepared statement
531
-
532
- ##### Catalog Introspection
533
-
534
- - `getCatalogs(): Promise<string[]>` – List available catalogs
535
- - `getSchemas(catalog?, schemaPattern?): Promise<Schema[]>` – List schemas
536
- - `getTables(options?): Promise<Table[]>` – List tables with filters
537
- - `getTableTypes(): Promise<string[]>` – List table type names
538
- - `getPrimaryKeys(table, catalog?, schema?): Promise<PrimaryKey[]>` – Get primary keys
539
- - `getExportedKeys(table, catalog?, schema?): Promise<ForeignKey[]>` – Get exported foreign keys
540
- - `getImportedKeys(table, catalog?, schema?): Promise<ForeignKey[]>` – Get imported foreign keys
541
-
542
- ##### Low-Level Flight Operations
543
-
544
- - `getFlightInfo(descriptor): Promise<FlightInfo>` – Get flight metadata
545
- - `doGet(ticket): AsyncIterable<RecordBatch>` – Fetch data by ticket
546
- - `doPut(descriptor, stream): Promise<void>` – Upload Arrow data
547
- - `doAction(type, body?): AsyncIterable<Result>` – Execute custom action
548
-
549
- ##### Connection Management
550
-
551
- - `connect(): Promise<void>` – Establish connection and authenticate
552
- - `close(): void` – Close connection and release resources
553
- - `isConnected(): boolean` – Check connection status
408
+ const subscription = client.subscribe("SELECT * FROM events", {
409
+ mode: SubscriptionMode.ChangesOnly,
410
+ heartbeatMs: 30_000
411
+ })
554
412
 
555
- ## Architecture
413
+ for await (const batch of subscription) {
414
+ console.log(`Received ${batch.numRows} rows`)
415
+ }
556
416
 
557
- ```
558
- ┌─────────────────────────────────────────────────────────┐
559
- │ FlightSqlClient │
560
- ├─────────────────────────────────────────────────────────┤
561
- │ Query Builder │ Prepared Statements │ Catalog API │
562
- ├─────────────────────────────────────────────────────────┤
563
- │ Flight SQL Protocol │
564
- │ (GetFlightInfo, DoGet, DoPut, DoAction) │
565
- ├─────────────────────────────────────────────────────────┤
566
- │ Protocol Buffers Layer │
567
- │ (FlightDescriptor, FlightInfo, etc.) │
568
- ├─────────────────────────────────────────────────────────┤
569
- │ gRPC Transport │
570
- │ (HTTP/2 + TLS + Auth Headers) │
571
- ├─────────────────────────────────────────────────────────┤
572
- │ Connection Pool │
573
- │ (Health checks, reconnection, backoff) │
574
- └─────────────────────────────────────────────────────────┘
417
+ // Cancel with AbortController
418
+ controller.abort()
419
+ // Or manually
420
+ await subscription.unsubscribe()
575
421
  ```
576
422
 
423
+ See the [API documentation](https://qualithm.github.io/arrow-flight-sql-js/) for full options.
424
+
577
425
  ## Compatibility
578
426
 
579
427
  ### Runtime Support
@@ -620,93 +468,6 @@ const result = await client.query("SELECT * FROM my_table")
620
468
  - Bidirectional streaming (`DoExchange`, `Handshake`) is not supported
621
469
  - Use bearer token auth via `setAuthToken()` instead of `Handshake`
622
470
 
623
- **Envoy gRPC-Web Proxy Example:**
624
-
625
- ```yaml
626
- # envoy.yaml
627
- static_resources:
628
- listeners:
629
- - address:
630
- socket_address:
631
- address: 0.0.0.0
632
- port_value: 8080
633
- filter_chains:
634
- - filters:
635
- - name: envoy.filters.network.http_connection_manager
636
- typed_config:
637
- "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
638
- codec_type: AUTO
639
- stat_prefix: ingress_http
640
- route_config:
641
- name: local_route
642
- virtual_hosts:
643
- - name: backend
644
- domains: ["*"]
645
- routes:
646
- - match: { prefix: "/" }
647
- route:
648
- cluster: flight_sql_backend
649
- cors:
650
- allow_origin_string_match:
651
- - prefix: "*"
652
- allow_methods: "GET, PUT, DELETE, POST, OPTIONS"
653
- allow_headers: "content-type,x-grpc-web,x-user-agent"
654
- expose_headers: "grpc-status,grpc-message"
655
- http_filters:
656
- - name: envoy.filters.http.grpc_web
657
- - name: envoy.filters.http.cors
658
- - name: envoy.filters.http.router
659
- clusters:
660
- - name: flight_sql_backend
661
- connect_timeout: 0.25s
662
- type: LOGICAL_DNS
663
- http2_protocol_options: {}
664
- lb_policy: ROUND_ROBIN
665
- load_assignment:
666
- cluster_name: flight_sql_backend
667
- endpoints:
668
- - lb_endpoints:
669
- - endpoint:
670
- address:
671
- socket_address:
672
- address: your-flight-sql-server
673
- port_value: 50051
674
- ```
675
-
676
- ### Flight SQL Servers
677
-
678
- Tested against:
679
-
680
- - Apache Arrow Flight SQL reference server
681
- - DuckDB Flight SQL extension
682
- - DataFusion Ballista
683
- - Custom lakehouse implementations
684
-
685
- ### Server Compatibility Matrix
686
-
687
- | Server | Version | Query | Prepared Stmt | Catalog | Subscriptions |
688
- | ---------------------- | ------- | ----- | ------------- | ------- | ------------- |
689
- | Arrow Flight SQL (ref) | 13.0+ | ✅ | ✅ | ✅ | ❌ |
690
- | DuckDB Flight SQL | 0.9+ | ✅ | ✅ | ✅ | ❌ |
691
- | DataFusion Ballista | 0.12+ | ✅ | ✅ | ✅ | ❌ |
692
- | Qualithm Lakehouse | 1.0+ | ✅ | ✅ | ✅ | ✅ |
693
-
694
- **Feature Support Notes:**
695
-
696
- - **Query**: Basic SQL query execution via `query()` and `execute()`
697
- - **Prepared Stmt**: Prepared statements with parameter binding
698
- - **Catalog**: `getCatalogs()`, `getSchemas()`, `getTables()`, `getSqlInfo()`, etc.
699
- - **Subscriptions**: Real-time streaming via `DoExchange` (server-specific feature)
700
-
701
- **Arrow Protocol Versions:**
702
-
703
- | Arrow Version | Flight SQL Version | Status |
704
- | ------------- | ------------------ | ----------------------- |
705
- | 18.0+ | 13.0+ | ✅ Fully supported |
706
- | 15.0-17.x | 13.0 | ✅ Supported |
707
- | 12.0-14.x | 12.0 | ⚠️ May work, not tested |
708
- | <12.0 | <12.0 | ❌ Not supported |
709
-
710
471
  ## Development
711
472
 
712
473
  ```bash
@@ -730,23 +491,8 @@ bun run format:fix
730
491
  bun run docs
731
492
  ```
732
493
 
733
- ## Flight SQL Protocol Reference
734
-
735
- This client implements the
736
- [Arrow Flight SQL specification](https://arrow.apache.org/docs/format/FlightSql.html):
737
-
738
- - **Flight SQL 13.0** – Current target version
739
- - Full protobuf message support
740
- - All standard actions (CreatePreparedStatement, ClosePreparedStatement, etc.)
741
- - Catalog introspection commands
742
- - Transaction support (where server supports it)
494
+ Implements [Arrow Flight SQL 13.0](https://arrow.apache.org/docs/format/FlightSql.html).
743
495
 
744
496
  ## License
745
497
 
746
498
  MIT
747
-
748
- ## Related Projects
749
-
750
- - [Apache Arrow](https://arrow.apache.org/) – The Arrow columnar format
751
- - [Arrow Flight](https://arrow.apache.org/docs/format/Flight.html) – High-performance data transport
752
- - [Arrow Flight SQL](https://arrow.apache.org/docs/format/FlightSql.html) – SQL over Flight
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qualithm/arrow-flight-sql-js",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Arrow Flight SQL client for JavaScript and TypeScript runtimes.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -91,6 +91,9 @@
91
91
  "@grpc/proto-loader": "0.8.0",
92
92
  "apache-arrow": "21.1.0"
93
93
  },
94
+ "overrides": {
95
+ "markdown-it": "14.1.1"
96
+ },
94
97
  "devDependencies": {
95
98
  "@eslint/js": "9.39.2",
96
99
  "@playwright/test": "1.58.2",
@@ -102,7 +105,7 @@
102
105
  "jiti": "2.6.1",
103
106
  "playwright": "1.58.2",
104
107
  "prettier": "3.8.1",
105
- "typedoc": "0.28.16",
108
+ "typedoc": "0.28.17",
106
109
  "typedoc-plugin-markdown": "4.10.0",
107
110
  "typescript": "5.9.3",
108
111
  "typescript-eslint": "8.55.0"