Skip to content

Follow-up: fix QueryBuilder JOIN methods to avoid retyping the same mutable instance #117

Description

@coderabbitai

Summary

The JOIN methods in packages/sqlite-wrapper/src/query-builder/index.ts currently mutate the existing QueryBuilder instance and then cast this to a new merged result type (for example QueryBuilder<T, ResultType & JT>). This can make older references to the same builder appear type-safe at compile time while executing a different joined query at runtime.

Why this matters

The current API contract suggests that methods like join, innerJoin, leftJoin, rightJoin, fullJoin, and crossJoin return a freshly typed builder. In practice they mutate shared state on the same instance. That mismatch can lead to unsound typing and surprising behavior when the same builder reference is reused.

Required changes

Choose one consistent approach for all JOIN methods:

  1. Preferred: return a fresh cloned builder instance before applying the JOIN, preserving correct type evolution, or
  2. keep the API mutable and do not widen the generic result type when returning this.

If the cloning approach is chosen, make sure the new builder preserves the current query state needed for chaining (for example WHERE clauses, params, ordering, limits, offsets, selected columns, and JOIN state as applicable).

Affected areas

  • packages/sqlite-wrapper/src/query-builder/index.ts
  • Potentially related state-sharing / cloning logic in:
    • packages/sqlite-wrapper/src/query-builder/select.ts
    • packages/sqlite-wrapper/src/query-builder/join.ts
    • packages/sqlite-wrapper/src/query-builder/base.ts
    • packages/sqlite-wrapper/src/types.ts

Acceptance criteria

  • All JOIN methods use one consistent correctness-preserving strategy.
  • The runtime behavior matches the public TypeScript return types.
  • Reusing an older builder reference cannot silently execute a differently typed joined query.
  • Tests cover the chosen behavior, especially around builder reuse after a JOIN chain.

Backlinks

Requested by @Its4Nik.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions