|
| 1 | +# Copilot Instructions for node-mssql |
| 2 | + |
| 3 | +## Build, Test, and Lint |
| 4 | + |
| 5 | +```bash |
| 6 | +npm test # Lint (standard) + unit tests |
| 7 | +npm run lint # StandardJS linter only (no config file — uses standard directly) |
| 8 | +npm run test-unit # Unit tests only (no database required) |
| 9 | +npm run test-tedious # Integration tests against a live SQL Server (tedious driver) |
| 10 | +npm run test-cli # CLI tool tests |
| 11 | +``` |
| 12 | + |
| 13 | +Run a single unit test: |
| 14 | + |
| 15 | +```bash |
| 16 | +npx mocha --exit -t 15000 --grep "test name" test/common/unit.js |
| 17 | +``` |
| 18 | + |
| 19 | +Integration tests require a running SQL Server instance configured in `test/.mssql.json` (see `.devcontainer/.mssql.json` for the expected shape). The devcontainer sets up both Node.js and SQL Server via Docker Compose. |
| 20 | + |
| 21 | +## Architecture |
| 22 | + |
| 23 | +This is a **driver-agnostic SQL Server client** for Node.js. The core abstraction is: |
| 24 | + |
| 25 | +- **`lib/base/`** — Abstract base classes (`ConnectionPool`, `Request`, `Transaction`, `PreparedStatement`) that define the public API. All extend `EventEmitter`. |
| 26 | +- **`lib/tedious/`** — Tedious driver implementation. Each file extends the corresponding base class and overrides private methods like `_poolCreate()`, `_executeQuery()`, etc. |
| 27 | +- **`lib/msnodesqlv8/`** — MSNodeSQLv8 (native ODBC) driver implementation. Same pattern. |
| 28 | +- **Entry points**: `index.js` and `tedious.js` both export `lib/tedious`; `msnodesqlv8.js` exports `lib/msnodesqlv8`. |
| 29 | + |
| 30 | +Driver index files use `Object.assign()` to merge base exports with driver-specific class overrides, then register the driver on the shared `driver` object in `lib/shared.js`. |
| 31 | + |
| 32 | +### Other key modules |
| 33 | + |
| 34 | +- **`lib/shared.js`** — Global mutable state: the active `driver`, configurable `Promise` library, and `map` (JS type → SQL type registry with `getTypeByValue()` auto-detection). |
| 35 | +- **`lib/global-connection.js`** — Singleton global connection pool with pre-connect handler registration. |
| 36 | +- **`lib/datatypes.js`** — SQL type definitions. Parameterized types are factory functions: `sql.VarChar(50)`, `sql.Numeric(18, 4)`. |
| 37 | +- **`lib/table.js`** — `Table` class for bulk inserts and TVPs. Parses qualified names like `[db].[schema].[table]`. |
| 38 | +- **`lib/error/`** — Error hierarchy: `MSSQLError` → `ConnectionError`, `RequestError`, `TransactionError`, `PreparedStatementError`. Each has a `code` property (e.g., `EINJECT`, `EARGS`, `EREQINPROG`). |
| 39 | + |
| 40 | +## Conventions |
| 41 | + |
| 42 | +- **Private methods** use a leading underscore (`_poolCreate`, `_executeQuery`). These are the driver-specific hooks that implementations override. |
| 43 | +- **Dual API**: All async methods support both Promises and callbacks. |
| 44 | +- **Streaming**: `Request` supports a `stream` mode where results are emitted as `row`, `recordset`, and `done` events. |
| 45 | +- **Linting**: StandardJS — no semicolons, 2-space indent, single quotes. No config overrides. |
| 46 | +- **Commit messages:** Follow [Conventional Commits](https://www.conventionalcommits.org/) enforced by commitlint. Semantic-release uses these to generate automated releases and changelogs, so correct commit types are critical. |
| 47 | + - `fix` — Bug fixes or behavioural corrections that don't change public interfaces. Triggers a **patch** release. |
| 48 | + - `feat` — New backwards-compatible functionality. Triggers a **minor** release. |
| 49 | + - `feat!` (or any type with `!`) — Breaking changes where consumers would need to update their code. Triggers a **major** release. |
| 50 | + - `chore` — Dependency updates, tooling changes, or housekeeping. **Does not trigger a release.** |
| 51 | + - `ci` — Changes to CI pipelines or workflow configuration. **Does not trigger a release.** |
| 52 | + - `style` — Refactoring or stylistic changes that do not change functionality. **Does not trigger a release.** |
| 53 | + - `test` — Changes that only touch test files. **Does not trigger a release.** |
| 54 | + - Only `fix` and `feat` trigger releases. If a change doesn't neatly fit `fix` or `feat` but still needs to be released, use whichever is most appropriate to ensure a release is created. |
| 55 | +- **Commits and merges:** |
| 56 | + - Commits should be atomic and ideally deployable in isolation — all tests, linting, and commitlinting should pass on each individual commit. |
| 57 | + - PRs are merged using a **merge commit** (no squash-merge or rebase-merge). Each commit in the PR history is preserved. |
| 58 | + - To keep branches up to date with the base branch, **rebase** onto it rather than merging it in. |
| 59 | + - All changes must go through a **pull request** — no direct commits to master. |
| 60 | +- **Debug logging**: Uses the `debug` library with `mssql:*` namespaces (`mssql:base`, `mssql:tedi`, etc.). |
| 61 | +- **Instance tracking**: `lib/utils.js` uses a `WeakMap` (`IDS`) to assign unique IDs to class instances. |
| 62 | +- **SQL injection guard**: Parameter names are validated against patterns like `--`, `/*`, `'` — throws `RequestError` with code `EINJECT`. |
| 63 | + |
| 64 | +### Test patterns |
| 65 | + |
| 66 | +- **Unit tests** (`test/common/unit.js`): No database needed. Tests type mapping, table parsing, error construction. |
| 67 | +- **Integration tests** (`test/common/tests.js`): Exported as a factory `(sql, driver) => { ... }` — called by each driver's test file. Many tests exercise three execution styles: callback, promise, and streaming. |
| 68 | +- **Framework**: Mocha + Node.js built-in `assert` (no chai/sinon). |
| 69 | +- **Keeping this file up to date:** If a change affects the architecture, conventions, build process, or any other information documented here, update this file as part of the same PR. |
0 commit comments