Repository navigation
fix(querybuilder): type several table options in one pipe call - #36
Merged
relsunkaev merged 3 commits intoNov 3, 2026
Merged
Conversation
A table piped with more than one option, as the README declares `memberships`, lost its column types: its columns became `BoundColumn<any, ...> | undefined`. The table-specific `pipe` overload accepts one option, so several options fell through to Effect's generic `Pipeable.pipe`. That signature cannot carry a table option, which is a generic function that needs the table as context, so each option's callback lost its table and the result widened to the generic table. Add overloads for two to nine options. Each option is typed against the table it is piped onto, keeps its validation argument, and the resulting table is computed from all of them at once rather than by nesting `ApplyOption`, which kept tables assignable to the generic table type. The new type tests check that one call with several options produces the same table type as one call per option. Two ddl type tests used a multi-option table whose columns had widened, so an index on a missing column was accepted; they now expect the error.
Effect 4.1.0 replaced `effect/Crypto` with the `effect/crypto/*` modules. effect-db still imports `effect/Crypto`, so a consumer that resolves the `^4.0.0` peer to 4.1 fails to load `effect-db/postgres/migrate` with ERR_MODULE_NOT_FOUND. The packed smoke test now fails on main for this reason. Cap both packages' Effect peer at `>=4.0.0 <4.1.0`. Also pin `@effect/platform-node-shared` to 4.0.0 in effect-db, alongside its other pinned Effect packages: `@effect/platform-node@4.0.0` accepts `^4.0.0` for it, which resolves to 4.1.1, and that release requires Effect ^4.1.1. Supporting Effect 4.1 means moving effect-db to the new crypto modules, which changes the `Crypto` requirement in its public `*Effect` signatures.
Contributor
Author
|
FYI, this lib is currently incompatible with effect |
Effect 4.0.3 changed `Crypto.randomUUIDv4` from an Effect into a method. Source discovery yielded it as an Effect, so `effectdb push` failed under any Effect from 4.0.3 with "yield* ... is not iterable". The packed CLI live smoke installs the newest Effect below 4.1 and hit this. The UUID only makes the temporary discovery module's file name unique, so take it from the platform's Web Crypto, which Node 22+ provides. The migration checksum's `Crypto.digest` is unchanged across 4.0.x.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #35
The README shows examples that use
.pipe(q1, q2, ...)but that loses its types. It only keeps its types if you do.pipe(q1).pipe(q2).pipe(q3)which I think we can both agree is comparatively ugly.Why
Problem: the README's
membershipstable loses its types. It pipes five options in one call, which leaves every column asBoundColumn<any, ...> | undefined. Queries over that table then fail with "excessively deep" errors, andQuery.ResultRowfalls back to an index signature. Chaining one option perpipecall keeps the types.pipeoverload inTableOptionPipeaccepts one option. With more, the call falls through to Effect's genericPipeable.pipe.Pipeable.pipecannot carry a table option, which is a generic function that needs the table as context. Each option's callback gets no table, and the result widens to the generic table type.Key Changes
Table
pipeoverloads (internal/table.ts):ApplyTableOptions: the last primary key and every option's conflict arbiters). NestingApplyOptionmade TypeScript unable to show that tables stay assignable to the generic table type.Type tests:
table-option-pipe-types.tschecks that one call with several options produces exactly the same table type as one call per option, for five options and for nine, and that columns and result rows keep their types.ddl-types.tschecks passed only because their multi-option table had widened, which let an index on a"missing"column through. They now expect the error.