Implement the mongo_count tool with unit tests #141

Closed
opened 2026-08-31 22:05:12 +00:00 by david · 1 comment
Owner

Summary

Implement the mongo_count tool — count documents matching a filter in a collection — with unit tests against a fake client.

Background

Depends on: #139

Part of the read-only tool surface of the mongodb extension. Answers "how many" questions without returning documents. The read-only boundary is enforced by construction: the tool calls only collection.countDocuments() — no write methods are reachable. db and collection are required. The extension connects lazily, so connection/auth failures surface here as categorized ToolErrors thrown from execute() (see src/errors.ts).

Documentation Required

A separate process downloads these into the listed folder before this issue is implemented. Check the folder for the actual reference material before starting.

docs/reference/mongodb-driver/ — for Collection.countDocuments:

Implementation Details

Create extensions/mongodb/src/tools/count.ts. Tool registered as mongo_count via pi.registerTool with a TypeBox parameter schema:

  • db (string, required) — database name
  • collection (string, required) — collection name
  • filter? (object) — EJSON filter (parsed with EJSON.parse; omit/{} when absent)

Behavior:

  1. EJSON.parse the filter (if provided).
  2. const count = await collection.countDocuments(filter) — wrap in try/catch; on error toToolError(err, context) (throws).
  3. Return the number as content and details: { count }.

Mirror the structure of src/tools/find.ts (sibling step) and the sibling extensions/postgres/src/tools/ implementations. Tests use a fake client with countDocuments returning a canned number, and record the received filter for assertions.

Write co-located tests in src/tools/count.test.ts:

  • Happy path: fake returns e.g. 42 → content is 42, details: { count: 42 }.
  • Filter parsed: an EJSON filter with $oid is passed to the fake as a real ObjectId.
  • Each error category (connection, auth, invalid, server, unexpected) surfaces as the categorized message.

Acceptance Criteria

  • Happy path returns the count and details: { count }.
  • An EJSON filter with $oid is passed to the driver as a real ObjectId.
  • All five error categories throw categorized ToolErrors with correct message prefixes.
  • bun test in extensions/mongodb/ is green for src/tools/count.ts.

Test Plan

cd extensions/mongodb
bun test   # count tool tests green
## Summary Implement the `mongo_count` tool — count documents matching a filter in a collection — with unit tests against a fake client. ## Background **Depends on:** #139 Part of the read-only tool surface of the mongodb extension. Answers "how many" questions without returning documents. The read-only boundary is enforced by construction: the tool calls only `collection.countDocuments()` — no write methods are reachable. `db` and `collection` are required. The extension connects lazily, so connection/auth failures surface here as categorized `ToolError`s thrown from `execute()` (see `src/errors.ts`). ## Documentation Required A separate process downloads these into the listed folder before this issue is implemented. Check the folder for the actual reference material before starting. **`docs/reference/mongodb-driver/`** — for `Collection.countDocuments`: - https://mongodb.github.io/node-mongodb-native/7.6/classes/Collection.html — API reference for `Collection.countDocuments(filter?, options?)` → `Promise<number>`. - https://www.mongodb.com/docs/drivers/node/current/crud/query/count/ — guide: `countDocuments()` behavior; an empty query returns the total document count; note certain query operators cannot be used with `countDocuments` (`$where`, `$near`, `$nearSphere` — it is implemented via the `$match` aggregation stage). - https://www.mongodb.com/docs/drivers/node/current/data-formats/extended-json/ — EJSON guide: `EJSON.parse()` for the filter parameter. ## Implementation Details Create `extensions/mongodb/src/tools/count.ts`. Tool registered as `mongo_count` via `pi.registerTool` with a TypeBox parameter schema: - `db` (string, **required**) — database name - `collection` (string, **required**) — collection name - `filter?` (object) — EJSON filter (parsed with `EJSON.parse`; omit/`{}` when absent) Behavior: 1. `EJSON.parse` the filter (if provided). 2. `const count = await collection.countDocuments(filter)` — wrap in try/catch; on error `toToolError(err, context)` (throws). 3. Return the number as content and `details: { count }`. Mirror the structure of `src/tools/find.ts` (sibling step) and the sibling `extensions/postgres/src/tools/` implementations. Tests use a fake client with `countDocuments` returning a canned number, and record the received filter for assertions. Write co-located tests in `src/tools/count.test.ts`: - Happy path: fake returns e.g. 42 → content is `42`, `details: { count: 42 }`. - Filter parsed: an EJSON filter with `$oid` is passed to the fake as a real ObjectId. - Each error category (connection, auth, invalid, server, unexpected) surfaces as the categorized message. ## Acceptance Criteria - [ ] Happy path returns the count and `details: { count }`. - [ ] An EJSON `filter` with `$oid` is passed to the driver as a real ObjectId. - [ ] All five error categories throw categorized `ToolError`s with correct message prefixes. - [ ] `bun test` in `extensions/mongodb/` is green for `src/tools/count.ts`. ## Test Plan ```bash cd extensions/mongodb bun test # count tool tests green ```
david closed this issue 2026-09-01 00:24:29 +00:00
Author
Owner

pi-loop opened and merged a pull request for this issue: #158

pi-loop opened and merged a pull request for this issue: https://git.excelera.net/david/pi-extensions-and-skills/pulls/158
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
david/pi-extensions-and-skills#141
No description provided.