Skip to content

feat(lint): adopt @constructive-io/eslint-config and fix repo-wide lint - #1570

Merged
pyramation merged 9 commits into
mainfrom
feat/eslint-config
Jul 31, 2026
Merged

feat(lint): adopt @constructive-io/eslint-config and fix repo-wide lint#1570
pyramation merged 9 commits into
mainfrom
feat/eslint-config

Conversation

@pyramation

@pyramation pyramation commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

pnpm lint has been failing repo-wide since the eslint 8→9 bump (eslint 9 only reads flat config; we only shipped .eslintrc.json). This consumes the shared flat config published from dev-utils (constructive-io/dev-utils#98) and gets pnpm lint to exit 0.

.eslintrc.json is deleted; eslint.config.mjs is the shared array plus repo-local adjustments. The bulk of the diff is one mechanical eslint . --fix commit (indentation + import sorting), kept separate from the config commit and from the ~20 files that needed a human.

Deviations from a literal port of .eslintrc.json

comma-dangle: ['error', 'never'] is dropped. It produced 57,145 errors — the codebase uses trailing commas essentially everywhere, and .prettierrc.json sets trailingComma: 'es5', so the rule and the formatter have been in direct contradiction (invisibly, since lint never ran). Prettier owns trailing commas now. If you'd rather enforce never, that's a separate mass-reformat, and prettier config has to change with it.

Generated and verbatim-copied files are ignored. Linting them is churn the next pnpm generate reverts — and in two cases it actually changes behavior:

  • codegen output: sdk/{constructive-cli,constructive-react,constructive-sdk}/src, sdk/migrate-client/src/migrate, **/__generated__/**, **/*.generated.ts, postgres/pg-ast/src/{asts,wrapped}.ts (~50k of the original errors)
  • graphql/codegen/src/core/codegen/templates/** — these are read verbatim at codegen time and written into every generated client, so import sorting there silently changes generated output (it broke the client-generator snapshots)
  • **/__fixtures__/** — codegen output snapshots and standalone sqitch/pgpm fixture projects that tests compare against

The sdk ignore is per-package rather than sdk/*/src/**: the latter left sdk/migrate-client with zero lintable files, which eslint treats as an error.

Rules turned off for idioms this repo relies on: no-namespace (declare global { namespace Grafast { ... } }), no-unsafe-function-type (Function in plugin/callback signatures), no-empty-object-type (StrictSelect<S, Shape> = ... ? {} : never). Scoped: no-control-regex off for pgpm/logger, no-unused-expressions off for **/*.type-test.ts.

linterOptions.reportUnusedDisableDirectives: 'off'. Worth knowing about: eslint 9 defaults it to warn, and --fix deletes disable comments it considers unused — including /* eslint-disable @typescript-eslint/no-empty-object-type */ at the top of a generated file, leaving a stray blank line the generator would re-add. Turning it off leaves ~30 existing directives intact.

Hand fixes (all semantics-preserving)

-return stmt && !stmt.hasOwnProperty('TransactionStmt');
+return stmt && !Object.prototype.hasOwnProperty.call(stmt, 'TransactionStmt');

-const tokenRe = /(^|[\s\[])([^\s\[\]@]+)(?=$|[\s\]@])/g;
+const tokenRe = /(^|[\s[])([^\s[\]@]+)(?=$|[\s\]@])/g;

 const info = project.getModuleInfo();
-info.version;

plus comments in empty catch {}/finally {} blocks, and two targeted disables (no-this-alias in MigrateTestFixture, no-async-promise-executor in s3-utils download — the executor is genuinely async and rewriting it is out of scope for a lint PR).

Verified

pnpm lint → 0 errors / 191 warnings (all no-unused-vars, warn by design). pnpm build clean, full CI green.

Follow-up

CI doesn't run lint — which is exactly why this rotted for a whole major version. Adding a lint job to run-tests.yaml is the thing that keeps it fixed.

Link to Devin session: https://app.devin.ai/sessions/3b5f5e76ddc74eda83a3543d7da2c75f
Requested by: @pyramation

ESLint 9 only reads flat config, so pnpm lint has been failing repo-wide since
the eslint 8 -> 9 bump. Replaces .eslintrc.json with an eslint.config.mjs on
top of the shared package, plus repo-local ignores for codegen output and a few
rule relaxations for idioms this repo relies on.
Mechanical output of `eslint . --fix` under the new flat config: indentation,
import sorting, unused-import removal. No behavior changes.
Semantics-preserving: Object.prototype.hasOwnProperty.call() instead of direct
hasOwnProperty access, redundant regex escapes dropped, comments in empty
blocks, a dead `info.version;` expression removed, and two targeted
eslint-disable comments (this-alias in a test fixture, async promise executor
in s3-utils download).
Ignoring all of sdk/*/src left sdk/migrate-client with nothing to lint, which
eslint treats as an error.
@pyramation pyramation self-assigned this Jul 31, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@socket-security

socket-security Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​constructive-io/​eslint-config@​0.2.0701008989100

View full report

graphql/codegen/src/core/codegen/templates/* are read verbatim at codegen time
and written into generated clients, so import sorting there changes generated
output and breaks client-generator snapshots.
They hold codegen output snapshots and standalone sqitch/pgpm fixture projects
that tests compare against; reformatting them is churn at best and a test
failure at worst.
@pyramation
pyramation merged commit 8aa7f39 into main Jul 31, 2026
17 checks passed
@pyramation
pyramation deleted the feat/eslint-config branch July 31, 2026 23:40
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