Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
228 commits
Select commit Hold shift + click to select a range
417ccbd
chore: add pull request review skill
glasstiger Aug 17, 2026
b3fdbaa
fix: omit nullish column values
glasstiger Aug 17, 2026
8d2629f
chore: update pull request review skill
glasstiger Aug 17, 2026
757fe17
feat(qwp): add browser-safe protocol core
glasstiger Aug 17, 2026
f233db2
feat(qwp): add websocket ingress sessions
glasstiger Aug 17, 2026
a44587d
feat(qwp): add egress query sessions
glasstiger Aug 17, 2026
253994b
test(qwp): add authenticated browser e2e
glasstiger Aug 17, 2026
eaa1705
feat(qwp): support durable acknowledgements
glasstiger Aug 17, 2026
22cd5fd
feat(qwp): negotiate server batch limits
glasstiger Aug 17, 2026
e2adc3b
feat(qwp): classify websocket upgrade failures
glasstiger Aug 17, 2026
6352720
feat(qwp): apply websocket send backpressure
glasstiger Aug 17, 2026
75c4484
feat(qwp): add reconnect failover and replay
glasstiger Aug 17, 2026
c98135a
feat(qwp): add typed query binds
glasstiger Aug 17, 2026
020d5d5
ci(qwp): dispatch Enterprise durable ack e2e
glasstiger Aug 17, 2026
dd775a7
feat(qwp): add high-level sender API
glasstiger Aug 17, 2026
e7e3953
feat(qwp): complete ingress symbol dictionary deltas
glasstiger Aug 17, 2026
c321750
feat(qwp): harden resource cleanup and timeouts
glasstiger Aug 17, 2026
331e6a4
feat(qwp): add zstd egress decompression
glasstiger Aug 17, 2026
d14f754
feat(qwp): complete compression negotiation and tuning
glasstiger Aug 17, 2026
a337486
feat(qwp): negotiate durable ACKs in browsers
glasstiger Aug 17, 2026
c27e72e
feat(qwp): automate egress credit and timeouts
glasstiger Aug 17, 2026
05f6c98
feat(qwp): split ingress batches to server cap
glasstiger Aug 18, 2026
49975c6
feat(qwp): bootstrap browser authentication sessions
glasstiger Aug 18, 2026
d5b6454
feat(qwp): add transactional sender mode
glasstiger Aug 18, 2026
62f9bf5
feat(qwp): add ingress observability metrics
glasstiger Aug 18, 2026
a635a5c
docs(qwp): document public API and migration
glasstiger Aug 18, 2026
0a9c0bc
fix(qwp): discard recovered deferred transaction tails
glasstiger Aug 18, 2026
0098ed3
fix(qwp): trim cumulative durable transaction ACKs
glasstiger Aug 18, 2026
7f96403
feat(qwp): add offline store-and-forward publishing
glasstiger Aug 18, 2026
c8f9135
fix(qwp): lock replay directories exclusively
glasstiger Aug 18, 2026
eff6f14
fix(qwp): bound egress cancellation draining
glasstiger Aug 18, 2026
69f5eaf
fix(qwp): bound egress buffering by default
glasstiger Aug 18, 2026
ffd7e7d
fix(qwp): detect poisoned ingress replays
glasstiger Aug 18, 2026
777f8ca
fix(qwp): preserve replay journal liveness
glasstiger Aug 18, 2026
88b2139
feat(qwp): add topology-aware endpoint routing
glasstiger Aug 18, 2026
b765899
feat(qwp): add pooled client facade
glasstiger Aug 18, 2026
3a7a431
feat(qwp): drain orphaned replay slots
glasstiger Aug 18, 2026
402e98e
feat(qwp): expose ingress ack watermarks
glasstiger Aug 18, 2026
3a48971
feat(qwp): add store-forward durability policies
glasstiger Aug 18, 2026
9652483
feat(qwp): add byte-based auto flush
glasstiger Aug 18, 2026
0d9c23b
feat(qwp): drain ingress on sender close
glasstiger Aug 18, 2026
3b96563
feat(qwp): add reusable egress column views
glasstiger Aug 18, 2026
9cfc95d
fix(qwp): reconcile durable symbol dictionary on publish failure
glasstiger Aug 18, 2026
5a8c71b
fix(qwp): fall back when symbol persistence fails
glasstiger Aug 18, 2026
85e9e66
fix(qwp): preserve borrowed resources during client close
glasstiger Aug 18, 2026
6e0f83b
feat(qwp): negotiate browser caps and compression
glasstiger Aug 18, 2026
4d63635
feat(qwp): align store-forward retry policies
glasstiger Aug 18, 2026
806e7a0
fix(qwp): retire drained symbol dictionaries
glasstiger Aug 18, 2026
209c7e8
feat(qwp): bound egress result batches
glasstiger Aug 18, 2026
c298ec7
feat(qwp): add reusable egress row views
glasstiger Aug 18, 2026
58bf575
fix(qwp): omit unsupported query flags
glasstiger Aug 18, 2026
a7e5611
fix(qwp): re-encode queries after failover
glasstiger Aug 18, 2026
1e27bc4
feat(qwp): expose failover server info
glasstiger Aug 18, 2026
3fbe982
feat(qwp): reap aged pooled connections
glasstiger Aug 18, 2026
4a57aa3
fix(qwp): close borrowed query sessions
glasstiger Aug 18, 2026
61fcd14
feat(qwp): split Node connection timeouts
glasstiger Aug 18, 2026
9c72dd3
feat(qwp): jitter reconnect backoff
glasstiger Aug 18, 2026
30f0c2f
feat(qwp): unify Node client configuration
glasstiger Aug 18, 2026
564cc68
docs(qwp): correct browser compression negotiation
glasstiger Aug 18, 2026
6bb56e9
fix(qwp): rotate endpoints after not-writable nack
glasstiger Aug 18, 2026
387f646
fix(qwp): recover persistent replay slots
glasstiger Aug 18, 2026
5e0b243
fix(qwp): align egress failover with Java client
glasstiger Aug 18, 2026
818379f
feat(qwp): enable ingress reconnect by default
glasstiger Aug 18, 2026
49f7a9e
fix(qwp): align unified config with Java client
glasstiger Aug 18, 2026
d5d9d9a
feat(qwp): isolate observability callbacks
glasstiger Aug 18, 2026
e975044
feat(qwp): add segmented replay and UDP ingress
glasstiger Aug 18, 2026
c302d81
fix(qwp): retain rows until local publication
glasstiger Aug 18, 2026
ba9cee6
fix(qwp): retry durable ack capability gaps
glasstiger Aug 18, 2026
2d834ff
fix(qwp): rebuild recoverable symbol sidecars
glasstiger Aug 18, 2026
3b54005
fix(qwp): report asynchronous sender failures
glasstiger Aug 18, 2026
40b6013
feat(qwp): expose current egress server info
glasstiger Aug 18, 2026
745054f
feat(qwp): unify browser cluster configuration
glasstiger Aug 19, 2026
f3b7739
feat(qwp): add fixed-segment replay store
glasstiger Aug 19, 2026
514da34
feat(qwp): adopt cross-client SFA persistence format
glasstiger Aug 19, 2026
3a9b092
fix(qwp): coordinate SFA ownership across clients
glasstiger Aug 19, 2026
ef07a22
fix(qwp): align identifier handling with Java
glasstiger Aug 19, 2026
948f1c1
fix(qwp): bound in-memory replay
glasstiger Aug 19, 2026
1d881d8
fix(qwp): align flush publication semantics
glasstiger Aug 19, 2026
8b737d8
fix(qwp): recover idle pooled SFA slots
glasstiger Aug 19, 2026
42722cc
fix(qwp): share failover health across drainers
glasstiger Aug 19, 2026
43debcf
feat(qwp): unify Sender WebSocket configuration
glasstiger Aug 19, 2026
1267de2
perf(qwp): decode result views ahead
glasstiger Aug 19, 2026
a39865d
fix(qwp): align egress flow control defaults
glasstiger Aug 19, 2026
61cb47f
perf(qwp): streamline store-and-forward persistence
glasstiger Aug 19, 2026
5579c5e
test(qwp): add performance benchmark suite
glasstiger Aug 19, 2026
9d751bd
feat(qwp): add compiled object-row table writers
glasstiger Aug 20, 2026
b8a57b3
feat(qwp): complete compiled writer column types
glasstiger Aug 20, 2026
b90d56e
fix(qwp): release the table selection on failed rows
glasstiger Aug 20, 2026
6170522
Merge remote-tracking branch 'origin/main' into ia_node_qwp
glasstiger Aug 20, 2026
55afb31
chore(qwp): extend the review skill to QWP
glasstiger Aug 20, 2026
b963ab9
feat(qwp): make the native locking module optional and lazily loaded
glasstiger Aug 20, 2026
9b31c06
fix(qwp): share the writer column brand across bundles
glasstiger Aug 20, 2026
2b871aa
fix(qwp): discard the row when a symbol value cannot be converted
glasstiger Aug 20, 2026
bf93367
fix(qwp): allocate frame sequences only for journalled frames
glasstiger Aug 20, 2026
a42fec5
fix(qwp): retry background segment maintenance instead of latching
glasstiger Aug 20, 2026
e42368a
fix(qwp): retry orphan slots that fail to drain transiently
glasstiger Aug 20, 2026
436d841
fix(qwp): release rows that cannot fit the negotiated batch cap
glasstiger Aug 20, 2026
b3f13a4
fix(qwp): encode DATE columns as timestamps on ingress
glasstiger Aug 20, 2026
91c9603
fix(qwp): trim the ingress wire log as cumulative ACKs arrive
glasstiger Aug 20, 2026
47ade10
Revert "fix(qwp): encode DATE columns as timestamps on ingress"
glasstiger Aug 20, 2026
4540b84
fix(qwp): roll back the schema a discarded row introduced
glasstiger Aug 20, 2026
70776f4
fix(qwp): parse ws/wss connect strings with one schema
glasstiger Aug 20, 2026
7629fbd
fix(qwp): match the Java close-flush timeout and always bound close()
glasstiger Aug 20, 2026
a644688
fix(qwp): retry an over-cap frame instead of failing the sender
glasstiger Aug 20, 2026
4717b60
fix(qwp): discard an over-cap batch on close, not on flush
glasstiger Aug 20, 2026
f05f9ae
docs: describe null and undefined column values
glasstiger Aug 20, 2026
2e8e514
docs(qwp): add a configuration-string key reference
glasstiger Aug 20, 2026
de9fac4
ci: enforce the browser, benchmark, and export-map gates
glasstiger Aug 20, 2026
7997f0b
test(qwp): close the mutation-proven coverage gaps
glasstiger Aug 20, 2026
ca78e94
fix(qwp): store a UUID passed as bytes in canonical order
glasstiger Aug 21, 2026
bd65a05
fix(qwp): walk failover endpoints on an opaque upgrade error
glasstiger Aug 21, 2026
e13f250
fix(qwp): keep UDP rows staged when a datagram cannot be encoded
glasstiger Aug 21, 2026
21d6145
fix(qwp): lock a decimal column's scale and keep its width stable
glasstiger Aug 21, 2026
00dae53
fix(qwp): bound egress recovery from an undecodable response
glasstiger Aug 21, 2026
0a236d8
fix(qwp): report journal bytes abandoned by torn-tail recovery
glasstiger Aug 21, 2026
c7be5bb
fix(qwp): retry a transient journal read instead of latching the sender
glasstiger Aug 21, 2026
a5f261a
fix(qwp): drop a frame's wire slot when a reconnect lands during its …
glasstiger Aug 21, 2026
3b5a746
fix(qwp): reject instead of throwing when flushing a closed sender
glasstiger Aug 21, 2026
bd4a224
fix(qwp): cancel a connect still negotiating when close() is called
glasstiger Aug 21, 2026
df1d952
fix(qwp): close the UDP socket when bind fails
glasstiger Aug 21, 2026
0092879
docs(qwp): state the auto-flush defaults and correct auto_flush_bytes
glasstiger Aug 21, 2026
da1132b
refactor(qwp): drop the unreachable resolved-sender constructor branch
glasstiger Aug 21, 2026
2ac6907
fix(qwp): keep compiled-writer row typing across published bundles
glasstiger Aug 21, 2026
822da58
ci: typecheck a consumer against the built declaration files
glasstiger Aug 21, 2026
4756867
test(qwp): pin which published classes can be named in a type position
glasstiger Aug 21, 2026
aabde6e
build(qwp): emit src/qwp/** as shared chunks instead of per-entry copies
glasstiger Aug 21, 2026
2399426
test(qwp): cover failover in a real browser
glasstiger Aug 21, 2026
a543a4f
ci: allow the build workflow to be dispatched manually
glasstiger Aug 21, 2026
5225cdd
refactor(qwp): replace the native slot lock with a pure-JS directory …
glasstiger Aug 21, 2026
68be1cc
fix(tcp): derive the JWK public point from the configured private key
glasstiger Aug 21, 2026
3360f67
test(qwp): drop browser tests that need a live QuestDB
glasstiger Aug 21, 2026
0a11537
ci: type-check test/** and fix what that surfaces
glasstiger Aug 21, 2026
a11f2dd
fix(ci): keep test/dist-types out of the test type-check
glasstiger Aug 21, 2026
3b494f5
fix(ci): make the build-artifact gate runnable
glasstiger Aug 21, 2026
93cbad4
fix(qwp): attach socket listeners before an aborted signal closes them
glasstiger Aug 21, 2026
5f305bf
fix(qwp): prove advisory-lock ownership with an acquisition token
glasstiger Aug 21, 2026
8870a28
fix(qwp): stop writing to a journal whose slot lock was reclaimed
glasstiger Aug 21, 2026
7aaf8df
fix: validate a column call even when its value is nullish
glasstiger Aug 21, 2026
be17047
fix(qwp): accept nullish words in long256Column
glasstiger Aug 21, 2026
1981bf2
fix(qwp): reject symbol IDs and encode options that cannot be honoured
glasstiger Aug 21, 2026
597991c
fix(qwp): bound decoded identifiers in bytes, not code units
glasstiger Aug 21, 2026
c754bfb
fix: make the QWP entry points reachable for docs and node10 consumers
glasstiger Aug 21, 2026
0606437
fix(qwp): stop close() from leaving connects and writes behind
glasstiger Aug 21, 2026
390c1bc
test(qwp): cover store-and-forward exclusion across real processes
glasstiger Aug 22, 2026
ce3ae47
fix(qwp): reject geohash and decimal values that cannot be encoded
glasstiger Aug 23, 2026
d7c90dc
fix(qwp): retry a transient journal fault raised while applying an ACK
glasstiger Aug 23, 2026
6e8951b
fix(qwp): quarantine an orphan slot whose head the server rejects
glasstiger Aug 23, 2026
a9a1948
fix(qwp): bound the grid a RESULT_BATCH declares, not only each dimen…
glasstiger Aug 23, 2026
89f0ee6
fix(qwp): close segment handles when the hot spare cannot be discarded
glasstiger Aug 23, 2026
18b2877
docs: generate the QWP entry points typedoc.json already declares
glasstiger Aug 23, 2026
81bb837
fix: discard a row that cannot be closed instead of wedging the sender
glasstiger Aug 23, 2026
0a1fccf
fix(qwp): keep auto-flush accurate when reset() lands during a flush
glasstiger Aug 23, 2026
5f2f692
fix(qwp): let an explicit connect_timeout bound the WebSocket upgrade
glasstiger Aug 23, 2026
4ea0f38
perf(qwp): decompress a RESULT_BATCH in place, not through a shifting…
glasstiger Aug 23, 2026
6417967
fix(qwp): retry a transient upgrade rejection instead of failing term…
glasstiger Aug 24, 2026
12f32f1
fix(qwp): stop a transient owner-record read from latching the slot lock
glasstiger Aug 24, 2026
6c3de06
fix(qwp): make the ACK watermark durable before the manifest that tri…
glasstiger Aug 24, 2026
6d02085
fix(qwp): keep a reclaimed journal from deleting the new owner's files
glasstiger Aug 24, 2026
ff32123
fix(qwp): retry a recoverable slot before quarantining it
glasstiger Aug 24, 2026
45a380a
perf(qwp): split UDP datagrams without re-encoding the batch each time
glasstiger Aug 24, 2026
68b06b4
fix(qwp): keep a QWP logger supplied without a top-level one
glasstiger Aug 24, 2026
de38f5a
fix(qwp): make the zstd over-run marker impossible to spell by accident
glasstiger Aug 24, 2026
266438f
fix(qwp): validate a column call even when its value is nullish
glasstiger Aug 24, 2026
0843b0e
fix(qwp): apply target and zone to ingress, not only egress
glasstiger Aug 24, 2026
26a190d
fix(qwp): let close() abort a connect that holds a store-and-forward …
glasstiger Aug 24, 2026
a645bf3
test(qwp): stop the auto-flush row trigger racing the interval trigger
glasstiger Aug 24, 2026
8f5a475
docs: name the client after JavaScript, not Node.js
glasstiger Aug 24, 2026
d9e0893
ci: point the Enterprise dispatch at the renamed e2e pipeline
glasstiger Aug 24, 2026
88311dd
fix(qwp): keep an async observability callback from crashing the host
glasstiger Aug 24, 2026
e3f7475
test(qwp): assert wss:// verifies certificates and preserves credentials
glasstiger Aug 24, 2026
c4fc77d
fix(qwp): validate nullish dateColumn and fixed-width decimal calls
glasstiger Aug 24, 2026
5745581
perf(qwp): drop the per-cell column-key rebuild on the ingest path
glasstiger Aug 25, 2026
8d2cf79
fix(qwp): send an all-nullish compiled-writer row instead of rejectin…
glasstiger Aug 25, 2026
fcebb9c
fix(qwp): point the udp-only relocation hint at udp, not http/tcp/udp
glasstiger Aug 25, 2026
e0b3611
fix(qwp): count rows a reset-interrupted flush already published
glasstiger Aug 25, 2026
687913b
fix(qwp): keep a parked append waiting through a self-healing trim fault
glasstiger Aug 25, 2026
c61f26e
test(qwp): count only payload bytes in the sfa-multiprocess marker check
glasstiger Aug 25, 2026
0dfee20
fix(qwp): reject an over-range ingress ACK instead of clamping it
glasstiger Aug 25, 2026
2bf90ff
fix(qwp): stop a stale advisory-lock holder from re-proving itself
glasstiger Aug 25, 2026
ea1bfb0
fix(qwp): stop a caller agent on wss from silently disabling tls_verify
glasstiger Aug 25, 2026
3a0b286
fix(qwp): bound the egress delta dictionary a RESULT_BATCH declares
glasstiger Aug 25, 2026
f2764bd
perf(qwp): drop two quadratic/redundant costs from the encoder hot path
glasstiger Aug 25, 2026
d7b2fdc
fix: validate the timestamp unit even when the value is nullish
glasstiger Aug 25, 2026
afc24fd
fix(qwp): install the default logger for ws::/wss:: connect strings
glasstiger Aug 25, 2026
e7a03e2
fix(qwp): wait out a self-healing trim fault met by a fresh append
glasstiger Aug 25, 2026
3854ca6
perf(qwp): slice a sparse table in ascending order without rescanning
glasstiger Aug 25, 2026
92bda6f
fix(qwp): validate the server decimal scale and drain views before a …
glasstiger Aug 25, 2026
de2c6f6
perf(qwp): lazy-load the QWP Node subsystem from the root entry
glasstiger Aug 25, 2026
73ed15c
fix(qwp): validate compressed delta bounds after decompression
glasstiger Aug 25, 2026
28e499b
fix(qwp): validate identifier limits in UTF-8 bytes
glasstiger Aug 25, 2026
6cec137
fix(qwp): preserve routing for pooled orphan recovery
glasstiger Aug 25, 2026
76e111e
fix(qwp): retry rate-limited browser bootstrap
glasstiger Aug 25, 2026
d5a16e4
test(qwp): settle trimming before lock reclamation
glasstiger Aug 25, 2026
afc4057
fix(qwp): preserve root failover endpoints
glasstiger Aug 25, 2026
ca8d23d
fix(qwp): accept signed packed IPv4 values
glasstiger Aug 25, 2026
0bb1adb
fix(qwp): require PEM TLS roots
glasstiger Aug 25, 2026
8c47a5e
fix(qwp): preserve ESM runtime identity
glasstiger Aug 26, 2026
303a6bb
fix(qwp): accept exponent decimal numbers
glasstiger Aug 26, 2026
818eb96
test(qwp): verify custom PEM root handshake
glasstiger Aug 26, 2026
5284c8f
fix(qwp): preserve typed ingress overrides
glasstiger Aug 26, 2026
de73067
fix(qwp): avoid ACK deadlines for browser polls
glasstiger Aug 26, 2026
f2aca2d
fix(qwp): require durable ACK negotiation for polling
glasstiger Aug 26, 2026
002b81d
fix(qwp): stop terminal replay retry loops
glasstiger Aug 26, 2026
b19302e
perf(qwp): lazy-load root QWP module
glasstiger Aug 26, 2026
d565bec
fix(qwp): warn when ignoring incompatible agents
glasstiger Aug 26, 2026
7c29d3a
fix(qwp): accept trusted certificate PEM roots
glasstiger Aug 26, 2026
6f71c99
fix(qwp): validate programmatic security options
glasstiger Aug 26, 2026
3eb4610
build: verify packed artifacts
glasstiger Aug 26, 2026
6634ca4
fix(qwp): report CRC tail data loss
glasstiger Aug 26, 2026
ac91f90
docs: update Sender transport semantics
glasstiger Aug 26, 2026
a7f9818
fix: statically load QWP node module
glasstiger Aug 27, 2026
0b66d49
fix: reset poison strikes during outages
glasstiger Aug 27, 2026
fb4a8b3
docs: clarify ILP auto-flush failure semantics
glasstiger Aug 27, 2026
425e936
fix: validate unsupported ILP columns consistently
glasstiger Aug 27, 2026
f9961fe
fix: retry transient QWP journal faults
glasstiger Aug 27, 2026
c044adc
docs(qwp): document numeric null sentinels
glasstiger Aug 27, 2026
c8576dd
fix(qwp): reject UDP authentication aliases
glasstiger Aug 27, 2026
38175c6
docs(qwp): document long-array ingestion limit
glasstiger Aug 27, 2026
5c891bf
fix(qwp): cap array dimensions at server limit
glasstiger Aug 27, 2026
a6df999
fix(qwp): keep mixed failover sweeps retryable
glasstiger Aug 27, 2026
c5d56f9
fix(qwp): bound browser session bootstrap
glasstiger Aug 27, 2026
e2d3094
fix(qwp): close direct sessions after NACK
glasstiger Aug 27, 2026
94bbecd
fix(qwp): retry unknown ingress statuses indefinitely
glasstiger Aug 28, 2026
913f8fb
fix(qwp): validate array dimensions before encoding
glasstiger Aug 28, 2026
405daf6
fix(qwp): validate timestamp units on null columns
glasstiger Aug 28, 2026
d347267
fix(qwp): cancel pool connections during shutdown
glasstiger Aug 28, 2026
be03ff0
fix(qwp): accept negative close flush timeouts
glasstiger Aug 28, 2026
5a67016
refactor: split Node.js and browser clients
glasstiger Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
857 changes: 857 additions & 0 deletions .claude/skills/review-pr/SKILL.md

Large diffs are not rendered by default.

124 changes: 122 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ on:
- main
pull_request:
schedule:
- cron: '15 2,10,18 * * *'
- cron: "15 2,10,18 * * *"
# GitHub disables a scheduled workflow after 60 days of repository
# inactivity, which stops it running on pull requests too. Dispatch is
# how to re-run it after that without pushing to a branch.
workflow_dispatch:

jobs:
test:
Expand All @@ -28,7 +32,7 @@ jobs:

- uses: pnpm/action-setup@v4
with:
version: 9
version: 10.12.4
run_install: true

- name: Linting
Expand All @@ -37,5 +41,121 @@ jobs:
- name: Type-checking
run: pnpm typecheck

# This contract uses DOM libraries with no @types/node and covers only
# the source graph shipped in @questdb/browser-client.
- name: Type-checking (browser)
run: pnpm typecheck:qwp-browser

# `pnpm typecheck` covers src plus a single contract file, so nothing
# type-checked test/** at all: a test could reference a deleted export
# and still pass, because vitest strips types without checking them.
- name: Type-checking (tests)
run: pnpm typecheck:test

- name: Type-checking (benchmarks)
run: pnpm typecheck:bench

- name: Linting (benchmarks)
run: pnpm lint:bench

- name: Tests
run: pnpm test

# Loads the built bundles through package.json `exports`, the way a
# consumer does, and verifies the two npm package boundaries.
- name: Built package tests
run: pnpm test:dist

# test:dist asserts runtime behaviour only. The compiled writers promise
# per-column row typing, which lives entirely in the emitted .d.ts files
# and is therefore invisible to source-level tests, where the public
# entries share one private-core module instance.
- name: Type-checking (built package consumer)
run: pnpm typecheck:dist

# The same gate publish.yml runs. Keeping it here too means a chunk that
# escapes `files`, or a regression in the check itself, fails a pull
# request instead of first being discovered during a release.
- name: Check for build artifacts
run: node scripts/check-build-artifacts.mjs

# Drives the built browser bundle in real Chromium against a local mock
# server. Tests that need a live QuestDB belong in the server repositories,
# where the topology and authentication fixtures already exist.
qwp-browser:
name: QWP browser bundle
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20

- uses: pnpm/action-setup@v4
with:
version: 10.12.4
run_install: true

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Browser bundle tests
run: pnpm test:qwp-browser

enterprise-qwp-e2e:
name: Dispatch Enterprise QWP E2E
runs-on: ubuntu-latest
# Azure credentials are not exposed to fork PRs. The repository variable
# keeps this dormant until the Enterprise pipeline and PAT are configured.
if: >-
vars.ENTERPRISE_E2E_ENABLED == 'true' &&
(github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository)
steps:
- name: Queue Enterprise TypeScript-client E2E
env:
ENT_DISPATCH_PAT: ${{ secrets.ENT_DISPATCH_PAT }}
CLIENT_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
CLIENT_PR_NUMBER: ${{ github.event.pull_request.number || '' }}
CLIENT_BRANCH: ${{ github.head_ref || github.ref_name }}
run: |
set -euo pipefail

if [ -z "${ENT_DISPATCH_PAT:-}" ]; then
echo "ENT_DISPATCH_PAT is not configured" >&2
exit 1
fi

ORG_URL="https://dev.azure.com/questdb/"
PROJECT="questdb-enterprise"
PIPELINE_NAME="build-and-test-e2e-javascript-client"
PIPELINES=$(curl -fsS -u ":${ENT_DISPATCH_PAT}" \
"${ORG_URL}${PROJECT}/_apis/pipelines?api-version=7.0")
PIPELINE_ID=$(echo "$PIPELINES" | jq -r --arg name "$PIPELINE_NAME" \
'.value[] | select(.name == $name) | .id' | head -1)
if [ -z "$PIPELINE_ID" ] || [ "$PIPELINE_ID" = "null" ]; then
echo "Enterprise pipeline '$PIPELINE_NAME' is not registered" >&2
exit 1
fi

BODY=$(jq -n \
--arg commit "$CLIENT_COMMIT" \
--arg pr "$CLIENT_PR_NUMBER" \
--arg branch "$CLIENT_BRANCH" \
'{
templateParameters: {
javascriptClientCommit: $commit,
javascriptClientPrNumber: $pr,
clientBranch: $branch
}
}')
RESPONSE=$(curl -fsS -u ":${ENT_DISPATCH_PAT}" \
-H "Content-Type: application/json" \
-X POST \
-d "$BODY" \
"${ORG_URL}${PROJECT}/_apis/pipelines/${PIPELINE_ID}/runs?api-version=7.0")
echo "Enterprise E2E queued: $(echo "$RESPONSE" | jq -r '._links.web.href')"
34 changes: 28 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:

- uses: pnpm/action-setup@v4
with:
version: 9
version: 10.12.4
run_install: true

- name: Linting
Expand All @@ -29,21 +29,43 @@ jobs:
- name: Type-checking
run: pnpm typecheck

# This contract uses DOM libraries with no @types/node and covers only
# the source graph shipped in @questdb/browser-client.
- name: Type-checking (browser)
run: pnpm typecheck:qwp-browser

- name: Tests
run: pnpm test

- name: Build
run: pnpm build

- name: Check for build artifacts
- name: Built package tests
run: pnpm exec vitest run --config vitest.dist.config.ts

# Guards the emitted .d.ts row typing, which no runtime suite can see.
- name: Type-checking (built package consumer)
run: |
[ -f dist/cjs/index.js ] || (echo "CJS build missing" && exit 1)
[ -f dist/es/index.mjs ] || (echo "ESM build missing" && exit 1)
pnpm exec tsc --noEmit -p tsconfig.dist-types.json
pnpm exec tsc --noEmit -p tsconfig.dist-types.cjs.json

# Checks both npm tarballs and follows every exported declaration and
# runtime module through its relative dependency graph.
- name: Check for build artifacts
run: node scripts/check-build-artifacts.mjs

- name: Publish @questdb/nodejs-client
uses: JS-DevTools/npm-publish@v3
with:
token: ${{ secrets.CI_TOKEN }}
access: public
strategy: all
package: packages/nodejs-client/package.json

- name: Publish
- name: Publish @questdb/browser-client
uses: JS-DevTools/npm-publish@v3
with:
token: ${{ secrets.CI_TOKEN }}
access: public
strategy: all
package: package.json
package: packages/browser-client/package.json
34 changes: 26 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,67 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

This is the QuestDB Node.js client library (@questdb/nodejs-client) that provides data ingestion capabilities to QuestDB databases. The client supports multiple transport protocols (HTTP/HTTPS, TCP/TCPS) and authentication methods.
This repository builds the QuestDB JavaScript clients: `@questdb/nodejs-client`
for Node.js and `@questdb/browser-client` for browsers. A private
`@questdb/client-core` workspace package owns their shared implementation.

## Development Commands

### Build

```bash
pnpm build # Build the library using bunchee (produces both ESM and CJS outputs)
pnpm build # Build both public ESM/CJS packages from client-core
```

### Testing

```bash
pnpm test # Run all tests using Vitest
```

### Code Quality

```bash
pnpm eslint # Run ESLint on all source files
pnpm typecheck # Run TypeScript type checking without emitting files
pnpm format # Format code using Prettier
```

### Documentation

```bash
pnpm docs # Build JSDoc documentation
pnpm run docs # Build TypeDoc documentation
pnpm preview:docs # Preview generated documentation locally
```

## Architecture

### Core Components

1. **Sender** (`src/sender.ts`): Main API class that orchestrates data ingestion. Handles auto-flushing, connection management, and provides the builder pattern API for constructing rows.
Runtime-neutral QWP implementation lives under `packages/client-core/src`.
Each public package owns its runtime-specific source, package metadata,
documentation, and single root build.

1. **Sender** (`packages/nodejs-client/src/sender.ts`): Main Node.js API class that orchestrates data ingestion. Handles auto-flushing, connection management, and provides the builder pattern API for constructing rows.

2. **Transport Layer** (`packages/nodejs-client/src/transport/`):

2. **Transport Layer** (`src/transport/`):
- `http/undici.ts`: Default HTTP transport using Undici library for high performance
- `http/stdlib.ts`: Alternative HTTP transport using Node.js built-in modules
- `tcp.ts`: TCP/TCPS transport for persistent connections with JWK authentication
- Protocol negotiation and retry logic for HTTP transports

3. **Buffer System** (`src/buffer/`):
3. **Buffer System** (`packages/nodejs-client/src/buffer/`):

- `bufferv1.ts`: Text-based protocol (version 1) for backward compatibility
- `bufferv2.ts`: Binary protocol (version 2) with double encoding and array support
- Dynamic buffer resizing and row-level transaction support

4. **Configuration** (`src/options.ts`): Comprehensive options parsing from connection strings with validation and deprecation handling.
4. **Configuration** (`packages/nodejs-client/src/options.ts`): Comprehensive options parsing from connection strings with validation and deprecation handling.

5. **QWP core** (`packages/client-core/src/qwp/` and `packages/client-core/src/_qwp/`): Shared browser-safe protocol/session code.

6. **Runtime adapters**: `packages/nodejs-client/src/qwp.ts` owns Node WebSocket, UDP, TLS, and persistence support; `packages/browser-client/src/index.ts` owns the browser WebSocket and authentication adapter. The browser package must remain free of Node built-ins, Node typings, `undici`, and `ws`.

### Protocol Versions

Expand All @@ -66,6 +82,7 @@ pnpm preview:docs # Preview generated documentation locally
## Testing Strategy

Tests are organized by component:

- `sender.config.test.ts`: Configuration parsing and validation
- `sender.buffer.test.ts`: Buffer operations and protocol serialization
- `sender.transport.test.ts`: Transport layer functionality
Expand All @@ -80,4 +97,5 @@ Integration tests use TestContainers to spin up QuestDB instances for realistic
- Buffer automatically resizes up to `max_buf_size` (default 100MB)
- Auto-flush triggers based on row count or time interval
- Each worker thread needs its own Sender instance (buffers cannot be shared)
- Protocol version 2 is recommended for new implementations with array column support
- Protocol version 2 is recommended for new implementations with array column support
- Run `pnpm test:dist` after package-boundary changes; it checks both npm tarballs, ESM/CJS loading, browser bundling, and the absence of Node modules from the browser artifact.
25 changes: 16 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
# Contributing to nodejs-questdb-client
# Contributing to the QuestDB JavaScript Client

Thank you for your interest in contributing to nodejs-questdb-client! This document provides guidelines and instructions for contributing to the project.
Thank you for your interest in contributing to the QuestDB JavaScript Client!
This repository contains both the Node.js and browser npm packages.

## Development Setup

1. Fork and clone the repository:

```bash
git clone https://github.com/YOUR_USERNAME/nodejs-questdb-client.git
cd nodejs-questdb-client
```

2. Install dependencies:

```bash
pnpm install
```


## Running Tests

The project uses Vitest for testing. Tests are located in the `test` directory.

1. Run tests in watch mode during development:

```bash
pnpm run test
```
Expand All @@ -30,8 +33,7 @@ pnpm run test
- Some tests use mock servers and certificates located in the `test/certs` directory

> You can generate the certificates by running the `generateCerts.sh` script in the `scripts` directory. The script requires two arguments: the output directory and the password for the certificates.
`./scripts/generateCerts.sh . questdbPwd123`

> `./scripts/generateCerts.sh . questdbPwd123`

## Code Style and Quality

Expand All @@ -40,23 +42,27 @@ pnpm run test
2. Format your code using Prettier

3. Lint your code:

```bash
pnpm run lint
pnpm eslint
```

4. Fix linting issues:

```bash
pnpm run lint --fix
pnpm eslint --fix
```

## Making Changes

1. Create a new branch for your changes:

```bash
git checkout -b feature/your-feature-name
```

2. Make your changes and commit them with clear, descriptive commit messages:

```bash
git add .
git commit -m "feat: add new feature"
Expand All @@ -65,6 +71,7 @@ git commit -m "feat: add new feature"
We follow the [Conventional Commits](https://www.conventionalcommits.org/) specification for commit messages.

3. Push your changes to your fork:

```bash
git push origin feature/your-feature-name
```
Expand All @@ -88,10 +95,10 @@ git push origin feature/your-feature-name
## Need Help?

If you have questions or need help, you can:

- Open an issue with your question
- Join our community discussions (if available)

## License

By contributing to nodejs-questdb-client, you agree that your contributions will be licensed under the project's license.

By contributing to the QuestDB JavaScript Client, you agree that your contributions will be licensed under the project's license.
Loading
Loading