Skip to content

Tml 2267 query builder unification#355

Open
wmadden wants to merge 23 commits intomainfrom
tml-2267-query-builder-unification
Open

Tml 2267 query builder unification#355
wmadden wants to merge 23 commits intomainfrom
tml-2267-query-builder-unification

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented Apr 19, 2026

Summary by CodeRabbit

  • New Features

    • Unified Mongo "query" builder (mongoQuery) with typed read/write flows, pipeline-style updates, find-and-modify terminals, and a raw-command escape hatch.
    • Write results now surface upsert metadata (upserted counts/ids).
  • Documentation

    • Docs, READMEs, examples, and runtime/client surfaces updated to reflect the renamed query builder and its capabilities.
  • Tests

    • New and updated tests covering writes, find-and-modify, pipeline updates, raw-command behavior, and end-to-end integration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 19, 2026

📝 Walkthrough

Walkthrough

Replaces the aggregation-focused pipeline-builder package with a broader typed Mongo query builder (@prisma-next/mongo-query-builder): introduces PipelineChain/CollectionHandle state machine, field-accessors and typed update ops, find-and-modify/upsert support, AST/command/result type updates, wire/driver propagation, many tests, and documentation/package renames.

Changes

Cohort / File(s) Summary
Docs & package metadata
docs/Architecture Overview.md, docs/.../Package-Layering.md, docs/reference/Package Naming Conventions.md, packages/2-mongo-family/5-query-builders/query-builder/DEVELOPING.md, packages/2-mongo-family/5-query-builders/query-builder/README.md, packages/2-mongo-family/5-query-builders/query-builder/package.json
Renamed package/docs from mongo-pipeline-buildermongo-query-builder; updated examples, README, DEVELOPING and package metadata to reflect query-builder scope (reads, writes, find-and-modify).
Removed pipeline-builder runtime & APIs
packages/.../pipeline-builder/src/{builder.ts,exports/index.ts,field-proxy.ts,filter-proxy.ts,pipeline.ts}, packages/2-mongo-family/5-query-builders/pipeline-builder/README.md
Deleted legacy pipeline-builder implementation, proxies, types, exports and README.
New query-builder core & exports
packages/2-mongo-family/5-query-builders/query-builder/src/{builder.ts,query.ts,exports/index.ts}
Added PipelineChain, mongoQuery/QueryRoot, consolidated public exports (acc, fn, PipelineChain, mongoQuery, createFieldAccessor, etc.).
State machine & handles
packages/2-mongo-family/5-query-builders/query-builder/src/{state-classes.ts,markers.ts}
Added CollectionHandle/FilteredCollection, runtime validators, marker types gating update/find-and-modify terminals, and factory createCollectionHandle.
Field accessor & update ops
packages/2-mongo-family/5-query-builders/query-builder/src/{field-accessor.ts,update-ops.ts,types.ts}
Added createFieldAccessor (callable/property accessor), Expression API, TypedUpdateOp union, folding/resolution helpers; removed old FieldProxy/FilterProxy types.
AST/commands & result types
packages/2-mongo-family/4-query/query-ast/src/{commands.ts,raw-commands.ts,query-plan.ts,result-types.ts,exports/execution.ts,filter-expressions.ts}
Extended Update/FindAndModify commands with upsert, sort, skip, returnDocument; made MongoQueryPlan generic over Command; added canonical result types and nin filter factory; re-exported result types.
Wire / transport updates
packages/2-mongo-family/6-transport/mongo-wire/src/{wire-commands.ts,results.ts}, packages/2-mongo-family/6-transport/mongo-wire/package.json
Wire commands now accept/propagate upsert, sort, skip, returnDocument; results re-export canonical types; package adds dependency on @prisma-next/mongo-query-ast.
Adapter / driver / runtime
packages/3-mongo-target/..., packages/3-extensions/mongo/src/runtime/mongo.ts, packages/3-mongo-target/3-mongo-driver/src/mongo-driver.ts
Adapter forwards new fields into wire commands; driver forwards upsert flag to Mongo and surfaces upsertedId/count; runtime API surface renamed pipelinequery and types updated.
Examples, tests & integration
examples/*, test/integration/*, packages/.../query-builder/test/*, examples/.../test/*
Replaced imports/usages from mongo-pipeline-builder/mongoPipeline to mongo-query-builder/mongoQuery; added extensive tests for writes, pipeline-style updates, find-and-modify, rawCommand, state-machine typing, and integration write tests using in-memory Mongo.
Misc package deps updates
examples/*/package.json, packages/2-mongo-family/7-runtime/package.json, packages/3-extensions/mongo/package.json, test/integration/package.json
Workspace dependencies updated from @prisma-next/mongo-pipeline-builder@prisma-next/mongo-query-builder.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant QueryRoot as "mongoQuery / QueryRoot"
    participant Collection as "CollectionHandle"
    participant Filtered as "FilteredCollection"
    participant Driver as "Mongo Driver / Wire"
    participant DB as "MongoDB"

    Client->>QueryRoot: mongoQuery(contractJson)
    QueryRoot->>Collection: from('orders')

    alt Unqualified insert
        Collection->>Driver: insertOne command (plan.meta.lane = "mongo-query")
        Driver->>DB: run insertOne(...)
        DB-->>Driver: Insert result
        Driver-->>Client: plan with InsertOneResult
    end

    alt Filtered update / find-and-modify
        Collection->>Filtered: match(filter)
        Filtered->>Driver: findOneAndUpdate / updateMany (includes upsert, sort?, skip?, returnDocument?)
        Driver->>DB: call findOneAndUpdate/update with options
        DB-->>Driver: Result (matched/modified and optional upsertedId/count)
        Driver-->>Client: plan with UpdateResult
    end

    alt Raw command escape hatch
        Client->>QueryRoot: rawCommand(AnyMongoCommand)
        QueryRoot->>Driver: wrap and forward command (requires storageHash)
        Driver->>DB: execute raw command
        DB-->>Driver: raw response
        Driver-->>Client: raw plan result
    end
Loading
sequenceDiagram
    participant Dev as Developer
    participant FieldAccessor
    participant Expression
    participant UpdateOps

    Dev->>FieldAccessor: f('a.b') or f.a.b
    FieldAccessor->>Expression: produce TypedAggExpr with _path

    alt Filter usage
        Expression->>Expression: .eq/.nin -> MongoFilterExpr
        Expression-->>Dev: filter callback yields MongoFieldFilter
    end

    alt Update usage
        Expression->>UpdateOps: .set/.inc/... -> TypedUpdateOp[]
        UpdateOps->>UpdateOps: resolveUpdaterResult / foldUpdateOps -> MongoUpdateSpec or pipeline stages
        UpdateOps-->>Dev: resolved update payload for terminal
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped from pipeline to query, light and spry,
New builders read, write, and nimbly modify;
Fields sing filters, updates fold with care,
Upserts travel wires — bold results laid bare;
A carrot-cheer for plans now fresh and spry!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Tml 2267 query builder unification' is vague and does not clearly summarize the main change. It references an issue ticket but lacks descriptive context about what 'query builder unification' entails. Revise the title to be more descriptive, e.g., 'Unify Mongo query and pipeline builders into single query-builder API' or 'Rename mongo-pipeline-builder to mongo-query-builder and extend query API'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2267-query-builder-unification

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 19, 2026

Open in StackBlitz

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-runtime@355

@prisma-next/family-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-mongo@355

@prisma-next/sql-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-runtime@355

@prisma-next/family-sql

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-sql@355

@prisma-next/middleware-telemetry

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/middleware-telemetry@355

@prisma-next/mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo@355

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-paradedb@355

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-pgvector@355

@prisma-next/postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/postgres@355

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-orm-client@355

@prisma-next/sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sqlite@355

@prisma-next/target-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-mongo@355

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-mongo@355

@prisma-next/driver-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-mongo@355

@prisma-next/contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract@355

@prisma-next/utils

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/utils@355

@prisma-next/config

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/config@355

@prisma-next/errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/errors@355

@prisma-next/framework-components

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/framework-components@355

@prisma-next/operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/operations@355

@prisma-next/contract-authoring

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract-authoring@355

@prisma-next/ids

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/ids@355

@prisma-next/psl-parser

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-parser@355

@prisma-next/psl-printer

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-printer@355

@prisma-next/cli

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/cli@355

@prisma-next/emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/emitter@355

@prisma-next/migration-tools

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/migration-tools@355

prisma-next

npm i https://pkg.pr.new/prisma/prisma-next@355

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/vite-plugin-contract-emit@355

@prisma-next/runtime-executor

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/runtime-executor@355

@prisma-next/mongo-codec

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-codec@355

@prisma-next/mongo-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract@355

@prisma-next/mongo-value

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-value@355

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-psl@355

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-ts@355

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-emitter@355

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-schema-ir@355

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-ast@355

@prisma-next/mongo-orm

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-orm@355

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-builder@355

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-lowering@355

@prisma-next/mongo-wire

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-wire@355

@prisma-next/sql-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract@355

@prisma-next/sql-errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-errors@355

@prisma-next/sql-operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-operations@355

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-schema-ir@355

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-psl@355

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-ts@355

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-emitter@355

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-lane-query-builder@355

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-relational-core@355

@prisma-next/sql-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-builder@355

@prisma-next/target-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-postgres@355

@prisma-next/target-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-sqlite@355

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-postgres@355

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-sqlite@355

@prisma-next/driver-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-postgres@355

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-sqlite@355

commit: fb64f40

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts (1)

60-66: ⚠️ Potential issue | 🟡 Minor

Pass command.upsert to wire command constructors in raw update lowering paths.

Lines 101 and 103 construct raw update wire commands without the upsert parameter, while the typed update paths (lines 61–66, 73–78) correctly pass command.upsert. Both RawUpdateOneCommand and RawUpdateManyCommand carry the upsert field, so raw lowering must propagate it to maintain consistent behavior.

Required fix
       case 'rawUpdateOne':
-        return new UpdateOneWireCommand(command.collection, command.filter, command.update);
+        return new UpdateOneWireCommand(
+          command.collection,
+          command.filter,
+          command.update,
+          command.upsert,
+        );
       case 'rawUpdateMany':
-        return new UpdateManyWireCommand(command.collection, command.filter, command.update);
+        return new UpdateManyWireCommand(
+          command.collection,
+          command.filter,
+          command.update,
+          command.upsert,
+        );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts` around lines 60
- 66, The raw-update lowering path is not propagating the upsert flag: when
creating RawUpdateOneCommand and RawUpdateManyCommand you must pass
command.upsert (just like the typed paths pass it to
UpdateOneWireCommand/UpdateManyWireCommand). Update the places that construct
RawUpdateOneCommand and RawUpdateManyCommand to include command.upsert as the
upsert argument (and ensure any helper like this.#lowerRawUpdate forwards that
value) so raw and typed update behavior is consistent.
🧹 Nitpick comments (5)
packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts (2)

136-140: Note the as unknown as MongoValue casts for protocol-specific values.

These casts handle MongoDB's wire protocol requirements where $unset expects an empty string and $rename expects a string value, but MongoValue may not include plain strings. The casts are pragmatic given the protocol constraints, though per coding guidelines blind casts are generally discouraged.

If feasible, consider widening MongoValue or using a dedicated wire-format type to avoid the casts, but this may be acceptable given MongoDB's protocol quirks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts`
around lines 136 - 140, The code in update-ops.ts uses blind casts "as unknown
as MongoValue" for $unset and $rename in the switch handling (see the case
blocks for '$unset' and '$rename'), which is brittle; either widen the
MongoValue type to include plain string values expected by the wire protocol or
introduce a dedicated wire-format type (e.g., WireMongoValue) and use that in
the ensure(...) return type for update builders; update the signatures/typedefs
referenced by ensure(...) and the surrounding update builder logic so you can
assign '' and entry.newName without unsafe casts, or if widening types is not
feasible, add a short typed helper (e.g., castToWireValue) used by the '$unset'
and '$rename' cases to centralize the unsafe conversion and document why it's
necessary.

151-160: Consider documenting the type coercion rationale.

The final cast buckets as unknown as Record<string, MongoValue> and the intermediate casts for $pullAll, $currentDate are necessary because the internal bucket structure (Record<string, Record<string, MongoValue>>) doesn't directly match the return type. This is correct at runtime since MongoDB expects this exact shape.

A brief inline comment explaining "bucket structure matches MongoUpdateSpec's non-pipeline form" would help future maintainers understand why the cast is safe.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts`
around lines 151 - 160, Add a brief inline comment near the final cast of
buckets (and the `$pullAll` / `$currentDate` assignments) explaining that the
internal type is Record<string, Record<string, MongoValue>> but we cast to
Record<string, MongoValue> because the assembled bucket structure matches
MongoDB's non-pipeline MongoUpdateSpec shape at runtime; reference the local
variable `buckets` and the update-op handling in this function (`$pullAll`,
`$currentDate`) so maintainers understand the coercion is intentional and safe.
examples/mongo-demo/src/db.ts (1)

13-13: Prefer query naming here too, not pipeline.

This file switched to mongoQuery but still exports pipeline, which keeps old semantics in the example API and makes migration less clear.

Suggested rename
-const pipeline = mongoQuery<Contract>({ contractJson });
+const query = mongoQuery<Contract>({ contractJson });
 ...
-  return { orm, runtime, pipeline, contract };
+  return { orm, runtime, query, contract };

As per coding guidelines: “Do not add backward-compatibility shims; update call sites instead.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/mongo-demo/src/db.ts` at line 13, The example exports a variable
named pipeline while using mongoQuery, causing mixed semantics; rename the
exported variable pipeline to query where it's declared (the line using
mongoQuery<Contract>({ contractJson })) and update any local exports or usages
to reference query so the API matches the new mongoQuery naming and avoids
keeping the old "pipeline" shim.
packages/3-extensions/mongo/src/runtime/mongo.ts (1)

39-39: Build query from the validated contract to keep surfaces consistent.

orm and runtime use contract from validateMongoContract, but query uses raw options.contractJson. If validation normalizes/enriches the contract shape, these surfaces can diverge.

Suggested fix
-  const query = mongoQuery<TContract>({ contractJson: options.contractJson });
+  const query = mongoQuery<TContract>({ contractJson: contract });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/3-extensions/mongo/src/runtime/mongo.ts` at line 39, Replace the use
of raw options.contractJson when constructing the query with the
validated/normalized contract returned by validateMongoContract: after calling
validateMongoContract(...) use the returned variable (e.g., contract) as the
input to mongoQuery<TContract> instead of options.contractJson so that the
query, runtime and orm all operate on the same validated/enriched contract
shape.
examples/retail-store/src/db.ts (1)

13-13: Rename pipeline to query to avoid carrying legacy API naming.

Now that this uses mongoQuery, keeping the exported field as pipeline looks like a compatibility shim and makes the example API inconsistent with the rest of the Mongo runtime surface.

Suggested rename
-const pipeline = mongoQuery<Contract>({ contractJson });
+const query = mongoQuery<Contract>({ contractJson });
 ...
-  return { orm, runtime, pipeline, raw, contract };
+  return { orm, runtime, query, raw, contract };

As per coding guidelines: “Do not add backward-compatibility shims; update call sites instead.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/retail-store/src/db.ts` at line 13, Rename the exported variable
named pipeline to query to remove legacy naming: change the const pipeline =
mongoQuery<Contract>({ contractJson }) binding to const query =
mongoQuery<Contract>({ contractJson }), update any local references and the
module export that still exposes pipeline to use query instead, and run a quick
search/replace for usages of pipeline in this example to update call sites to
query so there are no backward-compatibility shims left.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/2-mongo-family/5-query-builders/query-builder/README.md`:
- Line 5: Replace the transient project link
"projects/mongo-pipeline-builder/specs/query-builder-unification.spec.md" in the
README sentence about write terminals with a stable documentation path (for
example an architecture or package docs page under docs/ or packages/ that
covers the query-builder unification design); update the sentence to point to
that durable doc and remove dependence on the projects/ directory while keeping
the reference to TML-2267 if desired (edit the line containing the existing link
text to the new stable URL).

In `@packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts`:
- Around line 563-577: Remove the backwards-compatibility alias that resurfaces
the deprecated pipeline-builder name: delete the PipelineBuilder type alias and
the const PipelineBuilder = PipelineChain assignment so only PipelineChain
remains; then remove any re-exports of PipelineBuilder from your public exports
(so callers can no longer import the deprecated name) and update any internal
import sites that still reference PipelineBuilder to use PipelineChain (or
CollectionHandle/FilteredCollection) instead.
- Around line 81-93: The phantom-type markers U and F on PipelineChain are
currently unused because no conditional write terminals exist; either implement
the promised terminals (add methods updateMany, updateOne, findOneAndUpdate,
findOneAndDelete to class PipelineChain with signatures that are gated by the U
and F phantom parameters so their availability is reflected in the return types
and TypeScript constraints) or remove the marker plumbing entirely (strip U/F
from PipelineChain and all stage methods that toggle them). Also remove the
backward-compatibility alias PipelineBuilder and update any call sites to use
PipelineChain instead to comply with the guideline against shims.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/query.ts`:
- Around line 30-33: Change the mongoQuery API to require a typed contract at
the boundary: update the function signature of mongoQuery to accept
contractJson: TContract (not unknown) so callers must pass a validated contract;
inside mongoQuery remove the unsafe blind-cast and the secondary re-cast
(replace the `contract as unknown as MongoContract` usage with the already-typed
`contract` after you perform the storage-hash check), ensuring callers get
proper compile-time typing rather than a later runtime failure in from() or
rawCommand().

In `@packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts`:
- Around line 474-519: The findOneAndUpdate and findOneAndDelete signatures
currently claim they return MongoQueryPlan<ModelToDocShape<...>> but omit the
legitimate no-match/null case; update both return types to
MongoQueryPlan<ModelToDocShape<TContract, ModelName> | null> (i.e. include |
null) so callers are correctly typed for a missing document, and scan for any
other find-and-modify helpers in this file (e.g. any other findOne* methods) to
apply the same change to their return types.

In
`@packages/2-mongo-family/5-query-builders/query-builder/test/state-machine.test-d.ts`:
- Around line 16-40: Replace the current GetU and GetF helper types that use
explicit any placeholders and biome-ignore comments by using bare infer
placeholders so the type parameters are inferred directly from PipelineChain;
specifically update type GetU<T> to pattern-match T extends PipelineChain<infer
_TContract, infer _Shape, infer U, infer _F> ? U : never and update type GetF<T>
to pattern-match T extends PipelineChain<infer _TContract, infer _Shape, infer
_U, infer F> ? F : never, removing the any usages and the biome-ignore comments
while keeping the same exported type names.

---

Outside diff comments:
In `@packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts`:
- Around line 60-66: The raw-update lowering path is not propagating the upsert
flag: when creating RawUpdateOneCommand and RawUpdateManyCommand you must pass
command.upsert (just like the typed paths pass it to
UpdateOneWireCommand/UpdateManyWireCommand). Update the places that construct
RawUpdateOneCommand and RawUpdateManyCommand to include command.upsert as the
upsert argument (and ensure any helper like this.#lowerRawUpdate forwards that
value) so raw and typed update behavior is consistent.

---

Nitpick comments:
In `@examples/mongo-demo/src/db.ts`:
- Line 13: The example exports a variable named pipeline while using mongoQuery,
causing mixed semantics; rename the exported variable pipeline to query where
it's declared (the line using mongoQuery<Contract>({ contractJson })) and update
any local exports or usages to reference query so the API matches the new
mongoQuery naming and avoids keeping the old "pipeline" shim.

In `@examples/retail-store/src/db.ts`:
- Line 13: Rename the exported variable named pipeline to query to remove legacy
naming: change the const pipeline = mongoQuery<Contract>({ contractJson })
binding to const query = mongoQuery<Contract>({ contractJson }), update any
local references and the module export that still exposes pipeline to use query
instead, and run a quick search/replace for usages of pipeline in this example
to update call sites to query so there are no backward-compatibility shims left.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts`:
- Around line 136-140: The code in update-ops.ts uses blind casts "as unknown as
MongoValue" for $unset and $rename in the switch handling (see the case blocks
for '$unset' and '$rename'), which is brittle; either widen the MongoValue type
to include plain string values expected by the wire protocol or introduce a
dedicated wire-format type (e.g., WireMongoValue) and use that in the
ensure(...) return type for update builders; update the signatures/typedefs
referenced by ensure(...) and the surrounding update builder logic so you can
assign '' and entry.newName without unsafe casts, or if widening types is not
feasible, add a short typed helper (e.g., castToWireValue) used by the '$unset'
and '$rename' cases to centralize the unsafe conversion and document why it's
necessary.
- Around line 151-160: Add a brief inline comment near the final cast of buckets
(and the `$pullAll` / `$currentDate` assignments) explaining that the internal
type is Record<string, Record<string, MongoValue>> but we cast to Record<string,
MongoValue> because the assembled bucket structure matches MongoDB's
non-pipeline MongoUpdateSpec shape at runtime; reference the local variable
`buckets` and the update-op handling in this function (`$pullAll`,
`$currentDate`) so maintainers understand the coercion is intentional and safe.

In `@packages/3-extensions/mongo/src/runtime/mongo.ts`:
- Line 39: Replace the use of raw options.contractJson when constructing the
query with the validated/normalized contract returned by validateMongoContract:
after calling validateMongoContract(...) use the returned variable (e.g.,
contract) as the input to mongoQuery<TContract> instead of options.contractJson
so that the query, runtime and orm all operate on the same validated/enriched
contract shape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 195ea9d8-3158-47e7-b67a-a00ac60a6144

📥 Commits

Reviewing files that changed from the base of the PR and between a2d5169 and bbde782.

⛔ Files ignored due to path filters (6)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/mongo-migration-authoring/plans/data-migrations-plan.md is excluded by !projects/**
  • projects/mongo-migration-authoring/specs/data-migrations.spec.md is excluded by !projects/**
  • projects/mongo-pipeline-builder/plans/query-builder-unification-plan.md is excluded by !projects/**
  • projects/mongo-pipeline-builder/specs/query-builder-unification.spec.md is excluded by !projects/**
  • projects/one-package-install/plan.md is excluded by !projects/**
📒 Files selected for processing (58)
  • docs/Architecture Overview.md
  • docs/architecture docs/Package-Layering.md
  • docs/reference/Package Naming Conventions.md
  • examples/mongo-demo/package.json
  • examples/mongo-demo/src/db.ts
  • examples/mongo-demo/src/server.ts
  • examples/retail-store/package.json
  • examples/retail-store/src/data/events.ts
  • examples/retail-store/src/db.ts
  • examples/retail-store/test/setup.ts
  • packages/2-mongo-family/4-query/query-ast/src/commands.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/exports/index.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/field-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/filter-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/pipeline.ts
  • packages/2-mongo-family/5-query-builders/query-builder/DEVELOPING.md
  • packages/2-mongo-family/5-query-builders/query-builder/README.md
  • packages/2-mongo-family/5-query-builders/query-builder/package.json
  • packages/2-mongo-family/5-query-builders/query-builder/src/accumulator-helpers.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/exports/index.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/expression-helpers.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/field-accessor.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/markers.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/query.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/types.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/accumulator-helpers.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/accumulator-helpers.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder-new-stages.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/expression-helpers.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/expression-helpers.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/find-and-modify.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/fixtures/test-contract.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/raw-command.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine-surface.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/types.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/writes.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/tsconfig.json
  • packages/2-mongo-family/5-query-builders/query-builder/tsconfig.prod.json
  • packages/2-mongo-family/5-query-builders/query-builder/tsdown.config.ts
  • packages/2-mongo-family/5-query-builders/query-builder/vitest.config.ts
  • packages/2-mongo-family/6-transport/mongo-wire/src/results.ts
  • packages/2-mongo-family/6-transport/mongo-wire/src/wire-commands.ts
  • packages/2-mongo-family/7-runtime/package.json
  • packages/2-mongo-family/7-runtime/test/query-builder.test.ts
  • packages/2-mongo-family/7-runtime/test/runtime-types.test-d.ts
  • packages/3-extensions/mongo/package.json
  • packages/3-extensions/mongo/src/runtime/mongo.ts
  • packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts
  • packages/3-mongo-target/3-mongo-driver/src/mongo-driver.ts
  • test/integration/package.json
  • test/integration/test/mongo/query-builder.test.ts
💤 Files with no reviewable changes (5)
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/field-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/filter-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/exports/index.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/pipeline.ts

Comment thread packages/2-mongo-family/5-query-builders/query-builder/README.md Outdated
Comment thread packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts Outdated
Comment thread packages/2-mongo-family/5-query-builders/query-builder/src/query.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts (1)

479-513: ⚠️ Potential issue | 🟡 Minor

Include | null in find-and-modify return types for no-match case.

Both findOneAndUpdate and findOneAndDelete can legitimately return no document when the filter doesn't match any documents. The current return types omit this case, which could lead to runtime surprises.

🩹 Suggested fix
   findOneAndUpdate(
     updaterFn: (
       fields: FieldAccessor<ModelToDocShape<TContract, ModelName>>,
     ) => ReadonlyArray<UpdaterItem>,
     opts: { readonly upsert?: boolean; readonly returnDocument?: 'before' | 'after' } = {},
-  ): MongoQueryPlan<ModelToDocShape<TContract, ModelName>> {
+  ): MongoQueryPlan<ModelToDocShape<TContract, ModelName> | null> {
...
-  override findOneAndDelete(): MongoQueryPlan<ModelToDocShape<TContract, ModelName>> {
+  override findOneAndDelete(): MongoQueryPlan<ModelToDocShape<TContract, ModelName> | null> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts`
around lines 479 - 513, The return type of both methods findOneAndUpdate and
findOneAndDelete should include the possibility of no-match by allowing null;
update their signatures to return MongoQueryPlan<ModelToDocShape<TContract,
ModelName> | null> (or adjust the contained command/result type used by
MongoQueryPlan to accept null) so callers know a find-and-modify can yield null
when the filter matches nothing; update any related type references or factory
usage for FindOneAndUpdateCommand and FindOneAndDeleteCommand to accommodate the
nullable result type.
packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts (1)

797-811: 🛠️ Refactor suggestion | 🟠 Major

Remove the PipelineBuilder backward-compatibility alias.

Per coding guidelines: "Do not add backward-compatibility shims" and "Remove old code entirely instead of preserving it with backward-compatibility shims." The PipelineBuilder type alias and const assignment re-expose the deprecated name as a public API.

♻️ Suggested removal
-/**
- * Backwards-compatible alias for the previous read-only builder class. New
- * call sites should reference `PipelineChain` (or the higher-level
- * `CollectionHandle` / `FilteredCollection`) directly.
- *
- * `@deprecated` Use `PipelineChain` (or `CollectionHandle` / `FilteredCollection`)
- *   directly. Retained for the M0/M1 transition; will be removed once all
- *   internal references are migrated.
- */
-export type PipelineBuilder<
-  TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>,
-  Shape extends DocShape,
-> = PipelineChain<TContract, Shape, 'compat', 'compat'>;
-
-export const PipelineBuilder = PipelineChain;

Also remove the re-export from packages/2-mongo-family/5-query-builders/query-builder/src/exports/index.ts and update any internal call sites to use PipelineChain directly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts` around
lines 797 - 811, Remove the backwards-compatibility alias by deleting the
PipelineBuilder declarations (the type alias and the const assignment) so only
PipelineChain remains; also remove any export of PipelineBuilder from the
package's exports/index.ts and update all internal call sites that reference
PipelineBuilder to use PipelineChain directly (search for the symbol
"PipelineBuilder" across the repo and replace usages with "PipelineChain",
ensuring generic parameters and import paths still match).
🧹 Nitpick comments (1)
examples/mongo-demo/test/query-builder-writes.test.ts (1)

148-156: Consider using toMatchObject for related assertions.

Lines 150-152 use separate expect().toBe() calls for bio and name. Per coding guidelines, prefer object matchers when checking 2+ related values.

♻️ Suggested refactor
-        const doc = rows[0] as Record<string, unknown>;
-        expect(doc.bio).toBe('original');
-        expect(doc.name).toBe('Alice');
+        expect(rows[0]).toMatchObject({ bio: 'original', name: 'Alice' });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/mongo-demo/test/query-builder-writes.test.ts` around lines 148 -
156, Replace the two separate assertions on the returned document's fields with
a single object matcher: after obtaining rows via runtime.execute(plan) and
casting rows[0] to doc, use expect(doc).toMatchObject({ name: 'Alice', bio:
'original' }) instead of expect(doc.bio).toBe('original') and
expect(doc.name).toBe('Alice'); keep the length check and the persisted
usersCol().findOne assertion as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts`:
- Around line 797-811: Remove the backwards-compatibility alias by deleting the
PipelineBuilder declarations (the type alias and the const assignment) so only
PipelineChain remains; also remove any export of PipelineBuilder from the
package's exports/index.ts and update all internal call sites that reference
PipelineBuilder to use PipelineChain directly (search for the symbol
"PipelineBuilder" across the repo and replace usages with "PipelineChain",
ensuring generic parameters and import paths still match).

In `@packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts`:
- Around line 479-513: The return type of both methods findOneAndUpdate and
findOneAndDelete should include the possibility of no-match by allowing null;
update their signatures to return MongoQueryPlan<ModelToDocShape<TContract,
ModelName> | null> (or adjust the contained command/result type used by
MongoQueryPlan to accept null) so callers know a find-and-modify can yield null
when the filter matches nothing; update any related type references or factory
usage for FindOneAndUpdateCommand and FindOneAndDeleteCommand to accommodate the
nullable result type.

---

Nitpick comments:
In `@examples/mongo-demo/test/query-builder-writes.test.ts`:
- Around line 148-156: Replace the two separate assertions on the returned
document's fields with a single object matcher: after obtaining rows via
runtime.execute(plan) and casting rows[0] to doc, use
expect(doc).toMatchObject({ name: 'Alice', bio: 'original' }) instead of
expect(doc.bio).toBe('original') and expect(doc.name).toBe('Alice'); keep the
length check and the persisted usersCol().findOne assertion as-is.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 4f37e528-e4a5-4f3e-9d69-72e9bb81ae97

📥 Commits

Reviewing files that changed from the base of the PR and between bbde782 and 4e98ce8.

⛔ Files ignored due to path filters (2)
  • projects/mongo-pipeline-builder/plans/query-builder-unification-followups-plan.md is excluded by !projects/**
  • projects/mongo-pipeline-builder/plans/query-builder-unification-plan.md is excluded by !projects/**
📒 Files selected for processing (13)
  • examples/mongo-demo/test/query-builder-writes.test.ts
  • packages/2-mongo-family/4-query/query-ast/src/commands.ts
  • packages/2-mongo-family/4-query/query-ast/src/raw-commands.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/field-accessor.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/find-and-modify.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/pipeline-updates.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine-surface.test-d.ts
  • packages/2-mongo-family/6-transport/mongo-wire/src/wire-commands.ts
  • packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts
  • packages/3-mongo-target/3-mongo-driver/src/mongo-driver.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/find-and-modify.test.ts
  • packages/2-mongo-family/6-transport/mongo-wire/src/wire-commands.ts
  • packages/2-mongo-family/4-query/query-ast/src/commands.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts

@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented Apr 20, 2026

Addressed review feedback in 5304fdf:

Will address (done):

  • A01: Replaced transient projects/ spec link in README with stable DEVELOPING.md reference
  • A02: Removed deprecated PipelineBuilder alias from public surface
  • A04: Added | null to findOneAndUpdate/findOneAndDelete return types
  • A05: Refactored GetU/GetF helper types to use bare infer (removed biome-ignore + any)
  • A06d: Renamed pipelinequery variable in mongo-demo example
  • A06e: Used validated contract (not raw options.contractJson) in mongo extension runtime
  • A06f: Renamed pipelinequery variable in retail-store example (including downstream db.pipeline references)
  • A07c: Used toMatchObject instead of separate toBe assertions in integration test

Won't address:

  • A03: contractJson: unknown is intentional — JSON imports are typed as unknown; the generic TContract parameter provides compile-time safety

Not actionable:

  • A06a: Raw update commands intentionally omit upsert (raw commands pass through verbatim)
  • A06b/A06c: Wire-protocol casts are well-scoped and protocol-mandated
  • A07a/A07b: Duplicates of A04 and A02 respectively

wmadden added 21 commits April 20, 2026 16:49
Capture TML-2267 design decisions: rename @prisma-next/mongo-pipeline-builder
to @prisma-next/mongo-query-builder; split the single PipelineBuilder into a
three-state machine (CollectionHandle, FilteredCollection, PipelineChain) with
phantom UpdateCompat / FindAndModifyCompat markers; unify FieldProxy and
FilterProxy into the ADR-180 accessor; add typed terminals for inserts,
updates, deletes, upserts, find-and-modify, update-with-pipeline, and
$merge/$out. Plan organises the work into six milestones (M0 rename through
M5 close-out) with a per-criterion test coverage table.
… (M0)

Mechanical rename ahead of the query-builder unification (TML-2267):
- packages/2-mongo-family/5-query-builders/pipeline-builder/ -> .../query-builder/
- @prisma-next/mongo-pipeline-builder -> @prisma-next/mongo-query-builder
- mongoPipeline() -> mongoQuery(); PipelineRoot -> QueryRoot
- src/pipeline.ts -> src/query.ts
- @prisma-next/mongo extension: pipeline: -> query: on MongoClient/ConnectedMongoClient
- Update runtime tests, integration tests, examples, migration-authoring docs,
  Package-Layering, Architecture Overview, Naming Conventions

Read-side surface is unchanged. typecheck/lint/lint:deps clean; mongo-query-builder
(271 tests) and mongo-runtime (51 tests) suites pass.
…d field accessor (M1)

Splits the read-only PipelineBuilder into a three-state state machine — CollectionHandle, FilteredCollection, PipelineChain — gated by phantom UpdateCompat / FindAndModifyCompat markers per the spec marker table. CollectionHandle and FilteredCollection extend PipelineChain so the existing read-side surface keeps working unchanged.

Also replaces the separate FieldProxy and FilterProxy with a single ADR-180 unified FieldAccessor that exposes filter operators, the full set of update operators, and is callable as a dot-path accessor. Adds TypedUpdateOp + foldUpdateOps for the M2 write terminals.

State-machine type tests assert transitions and the marker table for representative pipeline-stage methods.
CollectionHandle gains the insert/unqualified-write surface (insertOne, insertMany, updateAll, deleteAll). FilteredCollection gains the filtered-write surface (updateMany, updateOne, deleteMany, deleteOne) which AND-folds the accumulated filters into the wire commands filter slot.

All terminals produce a MongoQueryPlan wrapping the existing AST commands (already supported end-to-end by mongo-adapter). Update terminals consume TypedUpdateOp callbacks and fold them via foldUpdateOps, which throws on operator+path collisions.

Tautological match-all is represented as _id $exists: true pending the Open Item #2 decision; centralised so the eventual switch is a one-line change.

Adds writes.test.ts asserting AST emission for every terminal and state-machine-surface.test-d.ts asserting that insert/unqualified-write methods are absent from FilteredCollection and filtered-write methods are absent from CollectionHandle.
- Extend `UpdateOneCommand`/`UpdateManyCommand` and the corresponding wire
  commands with an `upsert` flag; thread it through the adapter and driver.
  `Update{One,Many}Result` gains optional `upsertedCount`/`upsertedId`.
- `FilteredCollection.findOneAndUpdate(updaterFn, opts?)` and
  `.findOneAndDelete()` produce `FindOneAndUpdate{,Delete}Command` over the
  AND-folded filter. `returnDocument` is hardcoded `after` at the driver
  layer; making it caller-controllable is deferred.
- `CollectionHandle.upsertOne(filterFn, updaterFn)` and
  `FilteredCollection.upsertOne(updaterFn)` produce `UpdateOneCommand` with
  `upsert: true`. `upsertMany` deferred per the design discussion.
- Type tests assert find-and-modify is absent on `CollectionHandle`.

Deferred from the M3 scope:
- `PipelineChain<…, _, compat>.findOneAndUpdate/findOneAndDelete` — needs
  `sort`/`skip` slots on the find-and-modify AST/wire commands.
- `mongo-memory-server` integration coverage — to land in the wider
  M2/M3/M4 integration sweep.
- `PipelineChain.merge(opts)` and `.out(coll)` now return
  `MongoQueryPlan<unknown>` (lane `mongo-write`) directly rather than
  another `PipelineChain`. The `$merge`/`$out` stage is appended
  internally so the wire `AggregateCommand` ends with the terminal stage
  as Mongo requires.
- Existing tests updated to drop the trailing `.build()` and assert the
  new lane.

Deferred from M4:
- Pipeline-stage emitters on `FieldAccessor` (`f.set`, `f.replaceRoot`,
  ...) for the update-with-pipeline form (4.1/4.2).
- `PipelineChain<…, compat, _>.updateMany()` / `.updateOne()` no-arg
  consumption form (4.3) — marker gating already in place.
- `mongo-memory-server` integration coverage (4.6) — to land alongside
  the wider M2/M3/M4 integration sweep.
`mongoQuery(...).rawCommand(cmd)` packages any `AnyMongoCommand` (typed
CRUD or `RawMongoCommand` of `Document`s) into a `MongoQueryPlan<unknown>`
with `lane: mongo-raw`. The contract `storageHash` is validated eagerly
inside `rawCommand` so the type-test surface (which passes an `unknown`
contract for shape-only checks) continues to typecheck without a runtime
guard fight.

Deferred to the close-out PR:
- mongo-memory-server integration coverage for M2.7/M3.6/M4.6.
- Long-lived design content migration into the subsystem doc.
- `projects/mongo-pipeline-builder/` retirement.
…ocument (F1)

Add sort, skip, and returnDocument fields to FindOneAndUpdate/Delete
commands across the AST, raw-commands, wire-commands, adapter, and
driver layers. All fields default so existing call sites stay green.

The driver conditionally spreads sort into MongoDB options (skip is
carried on the wire command for F2 chain-deconstruction validation
but is not passed to the MongoDB driver since findAndModify does not
support skip at the wire level).

Surface returnDocument on FilteredCollection.findOneAndUpdate opts.
…gating (F2)

Add findOneAndUpdate/findOneAndDelete to PipelineChain, gated by the
FindAndModifyCompat marker via the this-parameter idiom. Stages that
clear the marker (group, limit, addFields, project, unwind, etc.)
make these terminals invisible at the type level.

Chain deconstruction walks accumulated stages, validates they are all
$match/$sort/$skip, AND-folds matches into a filter, and threads
sort/skip into the wire-command slots.

Brand fields (__updateCompat, __findAndModifyCompat) anchor the
phantom type parameters so structural typing respects the markers.

Extract foldUpdateOps into builder.ts imports to avoid a cyclic dep
between builder.ts and state-classes.ts.
…terminals (F3)

Add f.stage.set/unset/replaceRoot/replaceWith emitters to FieldAccessor
for producing MongoUpdatePipelineStage nodes in updater callbacks.

Add resolveUpdaterResult dispatcher that classifies updater arrays as
either TypedUpdateOp (folded into operator form) or pipeline stages
(passed through as-is), throwing on mixed arrays.

Add no-arg updateMany()/updateOne() on PipelineChain (gated on U=compat)
that deconstruct leading $match stages into a filter and validate
remaining stages are valid update-pipeline stages ($addFields, $project,
$replaceRoot).
14 end-to-end tests against mongo-memory-server covering M2 CRUD,
M3 find-and-modify/upserts, and M4 pipeline-style updates plus
merge/out. Reuses the existing mongo-demo harness rather than
standing up a new one. Updates both the follow-ups plan and parent
plan to mark F1–F4 tasks as completed.
- Remove deprecated PipelineBuilder alias from public surface
- Add | null to findOneAndUpdate/findOneAndDelete return types
- Replace transient projects/ spec link in README with stable path
- Refactor GetU/GetF helper types to use bare infer (drop biome-ignore)
- Rename pipeline → query in mongo-demo and retail-store examples
- Use validated contract in mongo extension runtime
- Use toMatchObject in integration test assertions
- Add MongoFieldFilter.nin() factory; use it in field-accessor instead of raw constructor
- Refactor deconstructUpdateChain loop from indexed for to for…of
- Improve PipelineChain.updateMany/updateOne error messages to explain the no-arg form
- Delete orphan FieldProxy/FilterProxy/FilterHandle types and their re-exports
UpdateCompat → UpdateEnabled (values: update-ok | update-cleared)
FindAndModifyCompat → FindAndModifyEnabled (values: fam-ok | fam-cleared)

The old shared literal "compat" was ambiguous in hovers and error messages
where both slots appeared as the same string. The new per-slot literals
are greppable and self-locating without counting comma positions.
Aligns with the repo-wide package-per-lane convention (mongo-orm uses
mongo-orm, sql-family uses sql). The three-lane split (mongo-pipeline,
mongo-write, mongo-raw) duplicated intent information already available
on the plan command discriminated union.
- Extract result interfaces to result-types.ts (breaks circular import)
- PipelineChain.updateMany/updateOne return UpdateResult instead of unknown
- PipelineChain.findOneAndUpdate/findOneAndDelete return ResolveRow|null
- FilteredCollection find-and-modify returns ResolveRow|null (matching parent)
- Add UpdaterResult type alias (union of homogeneous arrays) so mixed-shape
  updaters are a compile error, not just a runtime one
- Add @ts-expect-error rows for no-arg updateMany/updateOne unavailability
  after group/limit/sort stages
upsertMany is explicitly non-goal: MongoDB updateMany with upsert:true
inserts at most one document, making the name misleading. Also updates
all marker references in the spec to use the new UpdateEnabled /
FindAndModifyEnabled naming with self-identifying value literals.
Result interfaces (InsertOneResult, UpdateResult, DeleteResult, etc.)
are part of the primitive language definition and belong in the query
layer, not the transport layer. The transport layer (mongo-wire) now
re-exports from mongo-query-ast rather than owning the definitions.
Deletes the intermediate result-types.ts from query-builder.
Thread the specific command type through every terminal signature so
plan.command is narrowly typed without casts. The second type parameter
defaults to AnyMongoCommand, so existing consumers are unaffected.
Now that MongoQueryPlan carries the Command type parameter, plan.command
is narrowly typed at each terminal. The casts that were needed before
are redundant and their removal is the regression guard for the new
type parameter.
Replaces the read-only-focused README with a complete guide covering
the three-state machine, write terminals, field accessor, update
operators, pipeline-style updates, marker gating, rawCommand, and
observability. Reference tables for fn/acc helpers migrate to
DEVELOPING.md scope.
@wmadden wmadden force-pushed the tml-2267-query-builder-unification branch from 4e98ce8 to 7188cb1 Compare April 20, 2026 14:50
wmadden added 2 commits April 20, 2026 16:54
Use query instead of pipeline in setupTestDb so Db matches createClient.
out() and merge() already return MongoQueryPlan; calling build() was a type error.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts (1)

280-286: Redundant defensive check after length validation.

Lines 280-282 already ensure filters.length > 0, making the filters[0] === undefined check at lines 284-286 unreachable. TypeScript can't narrow array element access after length checks, so the guard is harmless, but consider using a non-null assertion instead:

const first = this.#filters[0]!;

That said, the explicit defensive check is acceptable as defense-in-depth.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts`
around lines 280 - 286, The code in FilteredCollection redundantly checks
filters[0] after already throwing when filters.length === 0; replace the
defensive runtime check by using a non-null assertion when reading the first
element (e.g. assign first from this.#filters[0]!) or otherwise rely on the
prior length check to avoid the unreachable throw; update the reference to the
private array (this.#filters) and the variable first in the
constructor/initializer so TypeScript knows the element is non-null without the
extra runtime branch.
packages/2-mongo-family/5-query-builders/query-builder/test/builder-new-stages.test.ts (1)

47-60: Consider consolidating related assertions with toMatchObject.

Per coding guidelines, prefer object matchers over multiple individual expect().toBe() calls when checking 2+ related values. The out() test could consolidate:

expect(plan).toMatchObject({
  meta: { lane: 'mongo-query' },
  command: { pipeline: expect.arrayContaining([expect.any(MongoOutStage)]) },
});
expect((plan.command.pipeline[0] as MongoOutStage).collection).toBe('results');

That said, the current assertions are clear and acceptable for terminal behavior tests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/2-mongo-family/5-query-builders/query-builder/test/builder-new-stages.test.ts`
around lines 47 - 60, Consolidate the related assertions in the out() test by
using an object matcher: replace the multiple expects that check plan.meta.lane
and that pipeline contains a MongoOutStage with a single
expect(plan).toMatchObject({ meta: { lane: 'mongo-query' }, command: { pipeline:
expect.arrayContaining([expect.any(MongoOutStage)]) } }) to assert structure,
and keep a focused assertion for the MongoOutStage.collection (accessed via
createOrdersBuilder().out(...).command.pipeline[0] as MongoOutStage) to verify
'results' (and similarly for the optional db parameter test assert stage.db ===
'archive'); this uses the existing createOrdersBuilder, out, MongoOutStage,
plan, and stage symbols to reduce repetitive checks while preserving intent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/2-mongo-family/4-query/query-ast/src/raw-commands.ts`:
- Around line 105-107: The types RawFindOneAndUpdateCommand and
RawFindOneAndDeleteCommand currently expose a skip field that is never used by
the driver; remove the skip property from those command interfaces (and from any
other raw-find-one command types referenced around the same blocks) and delete
any related references/uses so callers can't pass a no-op option; ensure
findOneAndUpdate and findOneAndDelete keep using only returnDocument/upsert/sort
as already implemented (update type names: RawFindOneAndUpdateCommand,
RawFindOneAndDeleteCommand, and any related definitions at the nearby sections)
so the type surface matches the actual driver behavior.

---

Nitpick comments:
In `@packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts`:
- Around line 280-286: The code in FilteredCollection redundantly checks
filters[0] after already throwing when filters.length === 0; replace the
defensive runtime check by using a non-null assertion when reading the first
element (e.g. assign first from this.#filters[0]!) or otherwise rely on the
prior length check to avoid the unreachable throw; update the reference to the
private array (this.#filters) and the variable first in the
constructor/initializer so TypeScript knows the element is non-null without the
extra runtime branch.

In
`@packages/2-mongo-family/5-query-builders/query-builder/test/builder-new-stages.test.ts`:
- Around line 47-60: Consolidate the related assertions in the out() test by
using an object matcher: replace the multiple expects that check plan.meta.lane
and that pipeline contains a MongoOutStage with a single
expect(plan).toMatchObject({ meta: { lane: 'mongo-query' }, command: { pipeline:
expect.arrayContaining([expect.any(MongoOutStage)]) } }) to assert structure,
and keep a focused assertion for the MongoOutStage.collection (accessed via
createOrdersBuilder().out(...).command.pipeline[0] as MongoOutStage) to verify
'results' (and similarly for the optional db parameter test assert stage.db ===
'archive'); this uses the existing createOrdersBuilder, out, MongoOutStage,
plan, and stage symbols to reduce repetitive checks while preserving intent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 1b498810-33af-4fe4-b20f-2c98c25362d2

📥 Commits

Reviewing files that changed from the base of the PR and between 4e98ce8 and 7188cb1.

⛔ Files ignored due to path filters (7)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/mongo-migration-authoring/plans/data-migrations-plan.md is excluded by !projects/**
  • projects/mongo-migration-authoring/specs/data-migrations.spec.md is excluded by !projects/**
  • projects/mongo-pipeline-builder/plans/query-builder-unification-followups-plan.md is excluded by !projects/**
  • projects/mongo-pipeline-builder/plans/query-builder-unification-plan.md is excluded by !projects/**
  • projects/mongo-pipeline-builder/specs/query-builder-unification.spec.md is excluded by !projects/**
  • projects/one-package-install/plan.md is excluded by !projects/**
📒 Files selected for processing (68)
  • docs/Architecture Overview.md
  • docs/architecture docs/Package-Layering.md
  • docs/reference/Package Naming Conventions.md
  • examples/mongo-demo/package.json
  • examples/mongo-demo/src/db.ts
  • examples/mongo-demo/src/server.ts
  • examples/mongo-demo/test/query-builder-writes.test.ts
  • examples/retail-store/package.json
  • examples/retail-store/src/data/events.ts
  • examples/retail-store/src/data/products.ts
  • examples/retail-store/src/db.ts
  • examples/retail-store/test/setup.ts
  • packages/2-mongo-family/4-query/query-ast/src/commands.ts
  • packages/2-mongo-family/4-query/query-ast/src/exports/execution.ts
  • packages/2-mongo-family/4-query/query-ast/src/filter-expressions.ts
  • packages/2-mongo-family/4-query/query-ast/src/query-plan.ts
  • packages/2-mongo-family/4-query/query-ast/src/raw-commands.ts
  • packages/2-mongo-family/4-query/query-ast/src/result-types.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/README.md
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/exports/index.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/field-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/filter-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/pipeline.ts
  • packages/2-mongo-family/5-query-builders/query-builder/DEVELOPING.md
  • packages/2-mongo-family/5-query-builders/query-builder/README.md
  • packages/2-mongo-family/5-query-builders/query-builder/package.json
  • packages/2-mongo-family/5-query-builders/query-builder/src/accumulator-helpers.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/exports/index.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/expression-helpers.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/field-accessor.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/markers.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/query.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/types.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/update-ops.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/accumulator-helpers.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/accumulator-helpers.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder-new-stages.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/expression-helpers.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/expression-helpers.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/find-and-modify.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/fixtures/test-contract.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/pipeline-updates.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/raw-command.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine-surface.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/types.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/writes.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/tsconfig.json
  • packages/2-mongo-family/5-query-builders/query-builder/tsconfig.prod.json
  • packages/2-mongo-family/5-query-builders/query-builder/tsdown.config.ts
  • packages/2-mongo-family/5-query-builders/query-builder/vitest.config.ts
  • packages/2-mongo-family/6-transport/mongo-wire/package.json
  • packages/2-mongo-family/6-transport/mongo-wire/src/results.ts
  • packages/2-mongo-family/6-transport/mongo-wire/src/wire-commands.ts
  • packages/2-mongo-family/7-runtime/package.json
  • packages/2-mongo-family/7-runtime/test/query-builder.test.ts
  • packages/2-mongo-family/7-runtime/test/runtime-types.test-d.ts
  • packages/3-extensions/mongo/package.json
  • packages/3-extensions/mongo/src/runtime/mongo.ts
  • packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts
  • packages/3-mongo-target/3-mongo-driver/src/mongo-driver.ts
  • test/integration/package.json
  • test/integration/test/mongo/query-builder.test.ts
💤 Files with no reviewable changes (6)
  • packages/2-mongo-family/5-query-builders/pipeline-builder/README.md
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/field-proxy.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/builder.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/pipeline.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/exports/index.ts
  • packages/2-mongo-family/5-query-builders/pipeline-builder/src/filter-proxy.ts
✅ Files skipped from review due to trivial changes (17)
  • examples/mongo-demo/package.json
  • docs/reference/Package Naming Conventions.md
  • packages/3-extensions/mongo/package.json
  • packages/2-mongo-family/6-transport/mongo-wire/package.json
  • packages/2-mongo-family/7-runtime/package.json
  • docs/Architecture Overview.md
  • examples/retail-store/test/setup.ts
  • examples/mongo-demo/src/server.ts
  • test/integration/test/mongo/query-builder.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/DEVELOPING.md
  • packages/2-mongo-family/7-runtime/test/query-builder.test.ts
  • packages/2-mongo-family/7-runtime/test/runtime-types.test-d.ts
  • docs/architecture docs/Package-Layering.md
  • test/integration/package.json
  • packages/2-mongo-family/6-transport/mongo-wire/src/results.ts
  • packages/2-mongo-family/4-query/query-ast/src/result-types.ts
  • packages/2-mongo-family/5-query-builders/query-builder/src/exports/index.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • examples/retail-store/package.json
  • packages/2-mongo-family/5-query-builders/query-builder/package.json
  • packages/3-mongo-target/3-mongo-driver/src/mongo-driver.ts
  • examples/retail-store/src/db.ts
  • packages/3-mongo-target/2-mongo-adapter/src/mongo-adapter.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/builder.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/raw-command.test.ts
  • packages/3-extensions/mongo/src/runtime/mongo.ts
  • examples/retail-store/src/data/events.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine.test-d.ts
  • packages/2-mongo-family/5-query-builders/query-builder/README.md
  • examples/mongo-demo/test/query-builder-writes.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/pipeline-updates.test.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/state-machine-surface.test-d.ts
  • examples/mongo-demo/src/db.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/writes.test.ts
  • packages/2-mongo-family/4-query/query-ast/src/commands.ts
  • packages/2-mongo-family/5-query-builders/query-builder/test/find-and-modify.test.ts

Comment on lines +105 to +107
readonly sort: Record<string, 1 | -1> | undefined;
readonly skip: number | undefined;
readonly returnDocument: 'before' | 'after';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Confirm skip is present in raw and wire command models"
rg -n --type=ts -C2 '\breadonly skip\b|constructor\(.+skip\?: number' \
  packages/2-mongo-family/4-query/query-ast/src/raw-commands.ts \
  packages/2-mongo-family/6-transport/mongo-wire/src/wire-commands.ts

echo
echo "2) Check mongo-driver execution paths for skip usage"
rg -n --type=ts -C4 'findOneAndUpdate|findOneAndDelete|cmd\.skip|skip:' \
  packages/3-mongo-target/3-mongo-driver/src/mongo-driver.ts

Repository: prisma/prisma-next

Length of output: 4158


Remove skip from find-and-modify command types or implement its handling in the driver.

skip is defined in both RawFindOneAndUpdateCommand (line 106) and RawFindOneAndDeleteCommand (line 135), but the MongoDB driver execution paths ignore it entirely:

  • findOneAndUpdate passes returnDocument, upsert, and conditionally sort, but never uses cmd.skip
  • findOneAndDelete passes only conditional sort, ignoring cmd.skip

This creates a misleading API where callers can provide skip with no effect. Either remove skip from these command types (since MongoDB's single-document operations don't support it) or implement proper handling in the driver.

Also applies to: 114-116, 123-125, 134-135, 137-143

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/4-query/query-ast/src/raw-commands.ts` around lines
105 - 107, The types RawFindOneAndUpdateCommand and RawFindOneAndDeleteCommand
currently expose a skip field that is never used by the driver; remove the skip
property from those command interfaces (and from any other raw-find-one command
types referenced around the same blocks) and delete any related references/uses
so callers can't pass a no-op option; ensure findOneAndUpdate and
findOneAndDelete keep using only returnDocument/upsert/sort as already
implemented (update type names: RawFindOneAndUpdateCommand,
RawFindOneAndDeleteCommand, and any related definitions at the nearby sections)
so the type surface matches the actual driver behavior.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
test/integration/test/mongo/query-builder.test.ts (2)

107-115: Optional: rename pipeline to query for DSL consistency.

The code works, but the old local name now conflicts with the new DSL terminology and can cause minor cognitive friction.

♻️ Suggested rename
-const pipeline = mongoQuery<TContract>({ contractJson });
+const query = mongoQuery<TContract>({ contractJson });

 function products() {
-  return pipeline.from('products');
+  return query.from('products');
 }

 function orders() {
-  return pipeline.from('orders');
+  return query.from('orders');
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/mongo/query-builder.test.ts` around lines 107 - 115,
Rename the local variable pipeline to query to match the DSL and avoid naming
friction: change the declaration const pipeline = mongoQuery<TContract>({
contractJson }) to const query = mongoQuery<TContract>({ contractJson }) and
update all usages inside the helper functions (e.g., pipeline.from in products()
and orders()) to use query.from instead; ensure tests import/expectations refer
to the new local name if any references exist.

169-740: Split this test file; it exceeds the 500-line limit.

This file is now 740 lines and should be split by existing functional describe groups (e.g., basic flow, aggregation, write terminals, advanced stages) to keep navigation and maintenance manageable.

As per coding guidelines, “Keep test files under 500 lines to maintain readability and navigability. If a test file exceeds this limit, it should be split into multiple files.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/mongo/query-builder.test.ts` around lines 169 - 740,
Current test file exceeds 500 lines; split it into multiple smaller test files
by grouping related describe blocks (e.g., "match + sort + limit + skip" for
basic pipeline flow, "group with accumulators" and other aggregation tests,
"out" and "merge" as write-terminal tests, and advanced stages like
"graphLookup", "setWindowFields", "redact", etc.). Extract the shared helpers
seed and exec and the describeWithMongoDB invocation into a small test helper
module so each new file can import them; move each logical describe(...) block
(refer to names like "match + sort + limit + skip", "group with accumulators",
"addFields", "project", "count", "unwind", "lookup", "facet", "bucket",
"unionWith", "sortByCount", "sample", "out", "merge", "bucketAuto", "redact",
"graphLookup", "setWindowFields", "complex pipeline", "named-args expression
helpers", "named-args accumulator helpers") into its own test file until each
file is under 500 lines, and update imports in those files to use the extracted
seed/exec helpers and describeWithMongoDB.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/integration/test/mongo/query-builder.test.ts`:
- Around line 107-115: Rename the local variable pipeline to query to match the
DSL and avoid naming friction: change the declaration const pipeline =
mongoQuery<TContract>({ contractJson }) to const query = mongoQuery<TContract>({
contractJson }) and update all usages inside the helper functions (e.g.,
pipeline.from in products() and orders()) to use query.from instead; ensure
tests import/expectations refer to the new local name if any references exist.
- Around line 169-740: Current test file exceeds 500 lines; split it into
multiple smaller test files by grouping related describe blocks (e.g., "match +
sort + limit + skip" for basic pipeline flow, "group with accumulators" and
other aggregation tests, "out" and "merge" as write-terminal tests, and advanced
stages like "graphLookup", "setWindowFields", "redact", etc.). Extract the
shared helpers seed and exec and the describeWithMongoDB invocation into a small
test helper module so each new file can import them; move each logical
describe(...) block (refer to names like "match + sort + limit + skip", "group
with accumulators", "addFields", "project", "count", "unwind", "lookup",
"facet", "bucket", "unionWith", "sortByCount", "sample", "out", "merge",
"bucketAuto", "redact", "graphLookup", "setWindowFields", "complex pipeline",
"named-args expression helpers", "named-args accumulator helpers") into its own
test file until each file is under 500 lines, and update imports in those files
to use the extracted seed/exec helpers and describeWithMongoDB.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: f6dbe063-35c9-4b0b-afe4-fe96035138da

📥 Commits

Reviewing files that changed from the base of the PR and between 7188cb1 and fb64f40.

📒 Files selected for processing (2)
  • examples/retail-store/test/setup.ts
  • test/integration/test/mongo/query-builder.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/retail-store/test/setup.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant