Skip to content

[absorbed into #630 Phase 2] create the package and move low-level request/URL mechanics #632

Description

@BorisTyshkevich

Part of #630.

Depends on: #631

Goal

Create an in-repo first-party workspace package named @altinity/clickhouse-http and move the low-level ClickHouse HTTP request/URL mechanics behind its public API without changing SQL Browser behavior.

This unit establishes the real package boundary. It does not yet move progress-stream parsing, ClickHouse error consumers, SQL Browser auth policy, product queries, or application services.

Architecture decision

Use packages/clickhouse-http/ as an npm workspace package. SQL Browser must consume it through the package name/public exports, not by importing packages/clickhouse-http/src/** directly.

The package must have no imports from src/** or any other SQL Browser implementation path.

Root npm ci, the existing single-file esbuild build, and the full test/type/architecture gate must continue to work. No new third-party runtime dependency is introduced; this is first-party source bundled into the existing artifact.

Required public API in this unit

The package must expose a low-level client equivalent to:

export interface ClickHouseHttpRequest {
  sql: string;
  defaultFormat: string;
  settings?: Record<string, string | number>;
  params?: Record<string, string | number>;
  authorization: string;
  signal?: AbortSignal;
}

export interface ClickHouseHttpClient {
  request(request: ClickHouseHttpRequest): Promise<Response>;
}

export interface ClickHouseHttpDeps {
  fetch(): typeof fetch;
  endpoint(): string;
}

export function createClickHouseHttpClient(deps: ClickHouseHttpDeps): ClickHouseHttpClient;

Exact symbol names may use the package's naming convention, but the contract above is fixed:

  • sql is opaque and unchanged;
  • authorization is the complete opaque header value;
  • dependency accessors are read live per request;
  • exactly one Fetch invocation;
  • native Response returned unchanged;
  • non-2xx resolves;
  • no body consumption;
  • no retry;
  • no token lookup;
  • no lifecycle callback;
  • caller signal is passed to the real Fetch request directly.

URL serialization

Move the implementation currently owned by chUrl() into the package as one authoritative URL builder used by request().

Preserve current SQL Browser wire behavior in this unit:

default_format=<caller value>
enable_http_compression=1
<settings serialized by key>
<params serialized by key>

params remains the current exact wire vocabulary. The package must not invent a second native-parameter abstraction yet: callers may supply param_*, query_id, session_id, role, and other ClickHouse query-string controls exactly as today.

Do not trim/filter truthy values in a way that changes current 0/empty-string serialization. Use one deterministic serializer and cover encoding with #631's contract cases.

SQL Browser integration

Keep the existing ClickHouseTransport seam temporarily so this PR is a narrow move rather than an application-wide rewrite.

src/net/clickhouse-http-transport.ts should become a compatibility adapter:

The reusable transport contract from #631 must run unchanged against the adapter and, where practical, directly against the package client so the new boundary is proven rather than only transitively assumed.

Workspace/package requirements

Add the minimal npm-workspace configuration needed for root npm ci to link the local package. The root app must import @altinity/clickhouse-http by package name.

Initial package layout:

packages/clickhouse-http/
  package.json
  src/
    index.ts
    client.ts
    url.ts
  tests/            # if package-local tests are the cleanest fit

The final independently publishable build/packaging surface is #638. This issue only needs a development-time workspace package that is isolated and testable.

Package metadata in this unit must include at least:

Do not add a runtime dependency to the package.

Architecture enforcement

Extend build/check-boundaries.mjs in this unit only as needed to enforce the new source boundary:

  • packages/clickhouse-http/** cannot import from root src/**;
  • root SQL Browser source may import the package public entrypoint, not packages/clickhouse-http/src/** internals.

The checks must be deterministic and run in npm run check:arch.

Tests

Package/request tests

Prove:

  • strict native Response identity;
  • one Fetch invocation on 2xx and non-2xx;
  • no body consumption;
  • exact SQL body;
  • opaque Authorization;
  • caller signal identity/passthrough;
  • live endpoint() and fetch() accessors;
  • current URL serialization/encoding;
  • no package import reaches SQL Browser source.

SQL Browser regression

The full #631 transport contract must remain green against the compatibility adapter.

Because workspace/dependency wiring changes the runtime module graph, run the relevant browser/e2e suite in addition to the full gate.

npm run check:types
npm run check:arch
npm run check:schemas
npm run check:examples
npm test
npm run build
npm run test:e2e

If the repository's targeted client browser suite is materially faster, run it during iteration; the final PR still needs the normal relevant e2e evidence required by /ship for dependency/workspace changes.

Acceptance criteria

Non-goals

  • Moving streamLines, parseExceptionText, findExceptionFrame, or StreamResult.
  • Adding queryJson, queryText, queryProgress, or killQuery convenience APIs.
  • Moving SQL quoting or ClickHouse type parsing.
  • Changing authedFetch, token refresh, credential epochs, auth classification, or connection state.
  • Deleting the SQL Browser transport compatibility seam yet.
  • Making the package publishable to npm yet; [absorbed into #630 Phase 8] make the package independently publishable and lock the boundary #638 owns that final isolation/build/pack step.
  • Creating the future dedicated GitHub repository.

Agent execution notes

Before planning, read #630, #631, root package.json/package-lock.json, tsconfig.json, build/build.mjs, build/check-boundaries.mjs, the current transport types/implementation, and the strengthened contract/browser tests. Keep this PR a behavior-preserving ownership move: package first, compatibility adapter second, no duplicate request implementation left behind.

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorRestructuring without user-facing behavior changetech-debt

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions