Repository navigation
Make lint runnable, cover the shipped lib/, and run it in CI - #458
Merged
Merged
Conversation
`npm run lint` now exits 0, lints the shipped JavaScript for the first time,
and runs as its own CI job.
Three separate problems, in increasing order of how much they mattered.
1. Nothing ran lint.
The `lint` script existed but no workflow called it, so breaking it cost
nothing - which is how a TypeScript major bump left typescript-eslint refusing
to load for weeks without a single red build. Added a `lint` job to test.yml.
It needs no SQL Server, no ODBC driver and no native build, so
`npm ci --ignore-scripts` is enough and it finishes in under a minute.
2. The shipped code was never linted.
eslint.config.mjs targets `lib/**/*.ts`, and the only .ts file in lib/ is
index.d.ts, which the very same block then ignores via `ignores: ['**/*.d.ts']`.
lib/ is 26 .js files. So the config looked like it covered the product code
while covering none of it, and `npm run lint` only ever checked 11 files in
test/ and samples/.
Added a lib/**/*.js block with the same stylistic rules, and widened the lint
scripts to include it. Stylistic rules only: eslint-config-love is type-aware
and expects a tsconfig project, which plain .js files here cannot supply. The
shipped code turned out to be in good shape - 4 violations, all whitespace,
all auto-fixed. `git diff -w` on lib/ is empty, so nothing changed but layout.
3. The 75 pre-existing violations.
62 went with --fix. Of the rest:
- 3 x no-promise-executor-return: `new Promise(resolve => setTimeout(...))`
returns the timer handle out of the executor. Braced.
- 1 x no-floating-promises: the async IIFE at the end of
samples/typescript/logger-example.ts had no catch, so any failure in the
sample became an unhandled rejection with a bare stack trace. Given a
catch that logs and sets exitCode.
- 11 x only-throw-error and 9 x no-non-null-assertion: turned off, with the
reasons recorded in the config. The first cannot be satisfied without
rewriting harness code that rethrows driver callback errors - QueryCb types
err as `Error | undefined`, but the overloaded query() signature leaves it
unresolvable at some call sites and cmd-test.ts declares several handlers as
`err: any`. The second is `res![0]` in tests that just inserted the row they
select. Both are consistent with the ~15 no-unsafe-* rules already off for
the same reason: the driver's own surface is loosely typed.
One autofix had to be reverted. `prefer-object-has-own` rewrote
`Object.prototype.hasOwnProperty.call(o, k)` to `Object.hasOwn(o, k)`, which
does not compile: tsconfig sets target es6 with no explicit lib, and
Object.hasOwn is es2022, so tsc failed with TS2550. Rule disabled and the
change reverted. Raising the target is the better fix, but it changes emitted
dist/ output and the generated declarations, so it belongs in its own change
rather than riding along with lint wiring.
Verified: npm run lint exits 0; npm run build and npm run build:test both exit
0; the driver still loads; connection-pool suite 42 passing and
query/connect suites 26 passing, which covers notifier.js and sql-client.js,
the two lib files touched.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5wuZia58hUzEqN7CvHtz9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
npm run lintnow exits 0, lints the shipped JavaScript for the first time, and runs as its own CI job.Three separate problems, in increasing order of how much they mattered.
1. Nothing ran lint
The
lintscript existed but no workflow called it — which is exactly how the TypeScript bump left typescript-eslint refusing to load for weeks with no red build. Lint that nothing runs is lint that rots.Added a
lintjob totest.yml. It needs no SQL Server, no ODBC driver and no native build, sonpm ci --ignore-scriptsis enough and it finishes in under a minute.2. The shipped code was never linted
This is the one worth knowing about.
eslint.config.mjstargetslib/**/*.ts— and the only.tsfile inlib/isindex.d.ts, which the very same config block then ignores viaignores: ['**/*.d.ts'].lib/is 26.jsfiles.So the config looked like it covered the product code while covering none of it, and
npm run lintonly ever checked 11 files intest/andsamples/.Added a
lib/**/*.jsblock and widened the lint scripts. Stylistic rules only —eslint-config-loveis type-aware and wants a tsconfig project, which plain.jshere can't supply.The good news: the shipped code was in decent shape — 4 violations, all whitespace, all auto-fixed.
git diff -wonlib/is empty, so nothing changed but layout.3. The 75 pre-existing violations
62 went with
--fix. Of the remainder:no-promise-executor-returnnew Promise(resolve => setTimeout(...))returns the timer handle out of the executor. Braced.no-floating-promiseslogger-example.tshad no catch, so any failure became an unhandled rejection with a bare stack trace. Now logs and setsexitCode.only-throw-errorno-non-null-assertionOn the two disables:
only-throw-errorcan't be satisfied without rewriting harness code that rethrows driver callback errors.QueryCbtypeserrasError | undefined, but the overloadedquery(sqlOrQuery, paramsOrCb?, cb?)signature leaves it unresolvable at some call sites, andcmd-test.tsdeclares several of its own handlers aserr: any. The second isres![0]in tests that just inserted the row they select. Both are consistent with the ~15no-unsafe-*rules already off for the same underlying reason — the driver's own surface is loosely typed.One autofix I had to revert
prefer-object-has-ownrewroteObject.prototype.hasOwnProperty.call(o, k)→Object.hasOwn(o, k), which does not compile:tsconfigsetstarget: es6with no explicitlib, andObject.hasOwnis ES2022, sotscfailed withTS2550.Rule disabled, change reverted. Raising the target is the better fix —
lib/*.jsalready usesObject.hasOwnat runtime, so only the TS lib setting lags — but it changes emitteddist/output and the generated declarations, so it wants its own PR rather than riding along with lint wiring.Verified
npm run lint→ exit 0npm run buildandnpm run build:test→ both exit 0connection-poolsuite 42 passing;query+connectsuites 26 passing — coveringnotifier.jsandsql-client.js, the twolib/files touched🤖 Generated with Claude Code
https://claude.ai/code/session_01K5wuZia58hUzEqN7CvHtz9