Repository navigation
fix: unbreak eslint . on main, and generate valid SQLite view DDL - #596
Merged
Merged
Conversation
Two unrelated fixes, both found by running the tooling rather than reading it.
1. ESLint error on main (blocks the release gate)
`npx eslint .` exited 1 on main:
packages/server/src/internal/driver-install.ts
335:7 error Unused eslint-disable directive
(no problems reported from 'security/detect-non-literal-fs-filename')
That rule does not cover `rmSync`, so the directive above it was dead and
`reportUnusedDisableDirectives` failed the run. Three CI jobs run plain
`npx eslint .` — build-gate's "ESLint", dependency-security's "ESLint
security" and release-gate's `eslint-security`, which the Release Draft
`needs` — so all three were red. Replaced the directive with a plain
comment that keeps the reasoning and says why no directive belongs there.
2. SQLite view migrations were never executable
Adding a view to a SQLite target produced:
CREATE OR REPLACE VIEW v_customer_orders AS
CREATE VIEW v_customer_orders AS
SELECT ...
-> near "OR": syntax error
Two independent defects:
- `sqlite_master.sql` is the whole `CREATE VIEW … AS …` text, and the
provider stored it in `definition`. The generator treats `definition` as
the *query* and emits the header itself, so the header appeared twice.
The SQL Server and DuckDB providers already strip their equivalent
headers for exactly this reason; SQLite was the outlier. Rather than add
a third copy of that regex, the stripping now lives in one tested helper
(`cores/view-definition.ts`) that SQLite uses. The two existing providers
keep their inline copies for now and could adopt it separately.
- SQLite has neither `CREATE OR REPLACE VIEW` nor `ALTER VIEW`, and the
dialect overrode neither hook, so it fell through to the generator's
Postgres-style default. Added `createViewStatement` (`CREATE VIEW IF NOT
EXISTS`, matching how this dialect emits indexes) and
`alterViewStatement` (`DROP VIEW IF EXISTS` + `CREATE VIEW`, since views
hold no data).
The stale comment at sql-generator.module.ts:1041 claiming "all other
dialects support CREATE OR REPLACE VIEW" is now wrong for SQLite; left
alone to keep this diff to the fix.
Verified end to end against the seeded demo databases: comparing demo_a to
demo_b now emits `CREATE VIEW IF NOT EXISTS …`, all three view statements
execute against a real SQLite target, and both migrated views are queryable.
Previously the added views failed outright.
npx vitest run 6874 passed, 1 expected fail, 145 skipped (was 6851)
npx eslint . exit 0 (one pre-existing exhaustive-deps warning remains)
npm run lint:security exit 0
npm run typecheck exit 0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ehcTb7vYMCawV1ajxwfxB
Contributor
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 691ac68c-3b0f-43ff-981c-b06b3f5d40e8) |
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.
Summary
Two unrelated fixes, both found by running the tooling rather than reading it.
1.
npx eslint .was failing onmain— this blocked the release gatesecurity/detect-non-literal-fs-filenamedoes not coverrmSync, so the directive above it was dead andreportUnusedDisableDirectivesfailed the run. Confirmed red in CI ona8dd395and5cf9b39.Three jobs run plain
npx eslint .— build-gate's ESLint, dependency-security's ESLint security and release-gate's eslint-security, which the Release Draftneeds— so all three were failing on one error.Replaced the directive with a plain comment that keeps the reasoning and records why no directive belongs there.
2. SQLite view migrations were never executable
Adding a view to a SQLite target produced:
Two independent defects:
sqlite_master.sqlis the wholeCREATE VIEW … AS …text, and the provider stored it indefinition. The generator treatsdefinitionas the query and emits the header itself, so it appeared twice. The SQL Server and DuckDB providers already strip their equivalent headers for exactly this reason — SQLite was the outlier.CREATE OR REPLACE VIEWnorALTER VIEW, and overrode neither hook, so it fell through to the generator's Postgres-style default.Changes
packages/server/src/internal/driver-install.tseslint-disablepackages/db/src/cores/view-definition.tsstripCreateViewHeader, one tested implementationpackages/db/src/providers/sqlLite/sqlLite.provider.tsdefinitionpackages/sql/src/providers/sqlLite/sqlite.sql-dialect.tscreateViewStatement+alterViewStatementcreateViewStatementemitsCREATE VIEW IF NOT EXISTS, matching how this dialect already emits indexes.alterViewStatementemitsDROP VIEW IF EXISTS+CREATE VIEW, since views hold no data.Notes for the reviewer
cores/view-definition.ts. The SQL Server and DuckDB providers keep their inline copies — I did not want to risk regressing two working providers in a bug fix. They can adopt the helper separately.detect-unsafe-regexsuppression is measured, not assumed. Every quantifier is over a bounded negated class or\w, and the only optional group (the schema qualifier) requires a literal.. Checked on 50 KB pathological inputs — a 50,000-char identifier, a whitespace run,a./arepetition, an unclosed paren and an unterminated quote, none of which reachAS— all matched in under 1 ms.const … =continuation line the directive lands on the wrong line and reads as unused — the same failure this PR fixes.sql-generator.module.ts:1041claims "all other dialects support CREATE OR REPLACE VIEW", which is now wrong for SQLite. Left as-is to keep this diff to the fix.Test plan
Verified end to end against the seeded demo databases, not only in unit tests:
Previously the added views failed outright.
npx vitest run— 6874 passed, 1 expected fail, 145 skipped (was 6851; +23 new tests)npx eslint .— exit 0npm run lint:security— exit 0npm run typecheck— exit 0bash scripts/seed/seed-all.sh sqlitethen comparedemo_a→demo_b, executing the generated migration against a copy of the targetOut of scope
Found while verifying, not touched here:
ResultsPanel.tsx:1047react-hooks/exhaustive-depswarning (does not fail CI;eslint.config.jssays each site needs a human decision)splitSqlStatementscuts aBEGIN … ENDtrigger body at its inner;— likely the most consequential of thesesqlite_autoindex_*namesADD COLUMNdefaults (DEFAULT strftime(...))isQuotedIdentifieremits a quote-wrapped identifier verbatim, which allows DDL injection from a source schema's column names — reported separately, needs a design decisionGenerated by Claude Code
Note
Medium Risk
Changes affect SQLite schema introspection and generated migration DDL (a common apply path), but scope is limited to view handling and a lint-only server fix with regression tests.
Overview
Unblocks
npx eslint .on main by removing a deadeslint-disableonrmSyncindriver-install.ts(the rule does not apply there, soreportUnusedDisableDirectivesfailed CI).SQLite view migrations are fixed in two places. The provider now runs
stripCreateViewHeaderonsqlite_master.sqlsodefinitionis only the query body, avoiding doubledCREATE VIEW … AS CREATE VIEW …when the generator re-emits the header. The SQLite dialect addscreateViewStatement(CREATE VIEW IF NOT EXISTS) andalterViewStatement(DROP VIEW IF EXISTS+CREATE VIEW) instead of Postgres-styleCREATE OR REPLACE VIEW/ALTER VIEW, which SQLite rejects.Shared
stripCreateViewHeaderlives inpackages/db/src/cores/view-definition.tswith broad unit tests; migration and dialect tests assert single-header output and unchanged Postgres behavior.Reviewed by Cursor Bugbot for commit 13d7580. Bugbot is set up for automated code reviews on this repo. Configure here.