refactor(service,database): seal live statements through Neon's drizzleAdapter()

Merged
CH
7d ago
+140-16

This PR changes no user-visible behaviour. A subscription delivers the same rows as before; only the way the service seals a statement changes. It's the second of three Realtime plumbing PRs split out of #3232, stacked on #4071. Every Realtime PR is on hold, so please don't merge it yet.

What it does

Neon's guide seals a Drizzle select through its Drizzle adapter, not through raw SQL built from toSQL().

  • LiveStatement.query: a live statement now carries the Drizzle select it was rendered from (LiveSelect). A statement that binds a Date doesn't carry it, because the adapter encodes no Date.
  • live/realtime.ts: the sealer calls createRealtime({ adapter: drizzleAdapter() }) and seals statement.query. A statement written as text alone, like the tests' stand-ins, still falls back to rawSql. The adapter also refuses a select whose key isn't the name Postgres answers the column under.
  • Dependencies: @neon/realtime-drizzle is pinned at 0.1.0. Its declared drizzle-orm peer is >=0.45.2 <0.46.0, but it only reads what 1.0.0-rc.4 builds the same way, so pnpm-workspace.yaml adds a peerDependencyRules entry allowing that version.
  • Tests: realtime.test.ts checks that the adapter takes a liveSelection select and refuses a renamed key. live-statements.test.ts now also seals every statement /api/live/inbox seals through the adapter.

Stack

  1. #4071, the immutability test helper (base main)
  2. This PR
  3. Shared host follow, live-follow.ts (base: this PR)
  4. #3232, the plan and agent scope inbox (base: PR 3)

Made with Luke