Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# AGENTS.md

This file provides guidance to AI coding agents (Claude Code, Codex, Copilot, Cursor, Aider, etc.) when working with code in this repository.

## Project Overview

This is the official MongoDB Node.js driver (`mongodb` npm package). It provides a TypeScript/JavaScript interface for applications to interact with MongoDB deployments. The driver implements the cross-driver MongoDB specifications.

## Common Commands

### Building

```bash
npm run build:ts # Compile TypeScript to lib/
npm run check:ts # Type-check without emitting
```

### Linting

```bash
npm run check:eslint # Run ESLint
npm run fix:eslint # Auto-fix ESLint issues
```

### Testing

Tests require a running MongoDB instance. To start one locally:

```bash
git submodule update --init
export DRIVERS_TOOLS=$(pwd)/drivers-evergreen-tools
Comment on lines +27 to +31
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

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

The statement "Tests require a running MongoDB instance" is inaccurate: npm run check:unit runs the unit test suite without needing a database (integration tests do). Consider rewording this section to say that integration tests require a running MongoDB deployment, or qualify which test commands need the orchestration steps below.

Copilot uses AI. Check for mistakes.
VERSION='latest' TOPOLOGY='replica_set' bash .evergreen/run-orchestration.sh
source mo-expansion.sh
```

```bash
npm run check:unit # Unit tests (no database required)
npm run check:test # Integration tests (requires database)
npm test # Lint + unit + integration
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

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

npm test runs more than just "Lint + unit + integration" in this repo (it also triggers the check:lint chain, which includes d.ts build / API Extractor / tsd checks). Consider updating the comment to reflect what npm test actually covers, or point readers at npm run check:lint + npm run test:all explicitly.

Suggested change
npm test # Lint + unit + integration
npm test # Full verification suite: check:lint chain + unit + integration
# Equivalent explicit commands: npm run check:lint && npm run test:all

Copilot uses AI. Check for mistakes.

# Run a single test by name pattern
npm run check:unit -- -g "pattern"
npm run check:test -- -g "pattern"
```

Tests use Mocha with 60-second timeout. Integration tests use a custom metadata UI that supports test filtering by topology, MongoDB version, auth, etc. via metadata:

```js
describe(
'my test',
{ metadata: { requires: { topology: ['replicaset'], mongodb: '>=6.0' } } },
function () {}
);
```

## Architecture

### Layered Design

```
Public API (MongoClient, Db, Collection, Cursors)
→ Operations (CRUD, Aggregation, Indexes, Bulk writes)
→ Sessions & Transactions
→ SDAM – Server Discovery And Monitoring (src/sdam/)
→ CMAP – Connection Management And Pooling (src/cmap/)
→ Wire Protocol & BSON serialization
```

### Key Source Directories

- **`src/operations/`** — Each database command is an `AbstractOperation` subclass. Operations declare aspects (retryable, read/write, explainable) via Symbols. `execute_operation.ts` is the central execution engine handling retries, sessions, server selection.
- **`src/sdam/`** — Topology discovery and monitoring. `topology.ts` manages servers, `server_selection.ts` picks the best server based on read preference and latency, `monitor.ts` sends periodic heartbeats.
- **`src/cmap/`** — Connection pooling per server, wire protocol encoding/decoding, authentication handshakes. `auth/` contains implementations for each auth mechanism (SCRAM, X.509, AWS, OIDC, Kerberos, PLAIN).
- **`src/cursor/`** — `AbstractCursor` base with lazy evaluation, async iteration, and streaming. Specialized cursors: `FindCursor`, `AggregationCursor`, `ChangeStreamCursor`, etc.
- **`src/bulk/`** — Ordered and unordered bulk write operations.
- **`src/client-side-encryption/`** — Auto-encryption and explicit encryption (CSFLE/Queryable Encryption).
- **`src/gridfs/`** — GridFS file storage using upload/download streams.

### How Operations Execute

1. User calls a method (e.g., `collection.insertOne()`)
2. An operation object is created (e.g., `InsertOperation`)
3. `executeOperation()` handles: implicit session creation → server selection → connection checkout → command building → wire protocol send → response handling → retry on transient errors
4. Connection returned to pool, session cleaned up

### Test Structure

- **`test/unit/`** — Mirrors `src/` structure. No database interaction, uses mocks.
- **`test/integration/`** — Real database tests organized by feature area.
- **`test/spec/`** — YAML/JSON test specifications from the cross-driver specs. Implemented by spec runners in integration tests. Files named `*.spec.test.ts` use standardized runners; `*.prose.test.ts` are hand-written prose test implementations.
- **`test/mongodb.ts`** — Central re-export of all `src/` internals for test access. Tests import from `../../mongodb` (or appropriate depth), never directly from `src/`.

## Code Conventions

- **No `export default`** — All exports must be named.
- **No TypeScript enums** — Use string unions or `as const` objects instead.
- **No `node:` import prefix** — Use bare module names (e.g., `import { setTimeout } from 'timers'`).
- **Timer/process imports** — Must import `setTimeout`, `setInterval`, `clearTimeout`, `process`, etc. from their modules, not use globals.
- **No `Buffer`** — Use `Uint8Array` in source code.
- **BSON imports** — Source code must import from `src/bson.ts`, not from the `bson` package directly.
- **Null/undefined checks** — Use loose equality (`== null`) not strict (`=== null` or `=== undefined`).
- **Type imports** — Use `import { type Foo }` (inline type imports).
- **`return await`** — Required in `src/` (enforced by `@typescript-eslint/return-await: always`).
- **Error messages** — Sentence case, no trailing period. Use driver-specific error types extending `MongoError`.
- **Formatting** — Prettier with single quotes, 2-space tabs, 100-char width, no trailing commas.

Comment on lines +105 to +106
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

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

The formatting bullet says "2-space tabs"; the repo config is tabWidth: 2, i.e., 2-space indentation. Consider rephrasing to avoid implying literal tab characters are required.

Copilot uses AI. Check for mistakes.
## Commit Messages

Follow [Conventional Commits](https://www.conventionalcommits.org/): `<type>(NODE-XXXX): <subject>`

Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`

Breaking changes use `!`: `feat(NODE-XXXX)!: description`
Loading