Repository navigation
feat(sql-editor): clause-aware completions, shared workspace scripts, multi-row peek filters - #539
Merged
Merged
Conversation
… the report Db2 returns system roles that hold nothing. Subtracting those from the shorter list of principals who have grants showed a negative user count. Co-authored-by: Cursor <cursoragent@cursor.com>
… multi-row peek filters Three pieces of SQL Editor work, plus a cleanup pass over all of it. Completions now know where the caret is. `completionSlot` reads the clause touching the caret and offers the next kind of name: tables (each with an alias) after FROM/JOIN, JOIN after LEFT/INNER/OUTER, and alias.column plus common functions after ON/WHERE/AND. A space after one of those keywords opens the popup, which Monaco skips on its own whenever quick suggestions are on. The slim editor build also had to pull in suggestController, without which providers register and never appear. Data Peek filters take several rows: WHERE conditions joined with AND, and an ORDER BY list with a direction per column. Workspace scripts (migration 31) put SQL on the server instead of the browser, so every member of a workspace opens the same text. Viewers read them; editors and owners save and delete. The editor textarea is kept out of the browser's password manager — signing in on this origin taught Chrome the site has a login, and Enter in Monaco then asked macOS to unlock saved passwords. Cleanup applied over the above: - `splitPeekList` re-implemented `splitSelectItems`, which tablePreview.ts already imports. Generalised the existing scanner to `splitTopLevel(text, sep)` and deleted the copy, which also fixes `a,b` and [a,b] splitting mid-identifier. - Deleted `isInFromTablePosition`: `completionSlot` replaced it and it had no caller left but its own test. - completion.ts: one keyword table drives the word set, the scan regex and the slot lookup; `buildTableIndex` is lazy instead of rebuilt per keystroke; `qualifiedTableName` is a map lookup instead of an O(tables^2) rescan; the literal-stripping pass runs once per keystroke instead of twice. - Both Data Peek clear buttons call the existing `apply()` rather than inlining it; one helper builds the per-row test ids. - `runScriptOp` replaces two identical handlers and resets busy in `finally`; a save no longer refetches what the POST already returned. - AccessReport uses the report's own `roleCount` again, so "how many are roles" has one definition. - Declared the three new routes in the HTTP contract and registered the new e2e suite in run-all.mjs — both guards were failing, and the suite would never have run. Gates: apps/web tsc clean (it was failing on `onDidType`), 6306 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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: 0850b0ff-94f4-444a-be76-fac98215f6e7) |
Contributor
Test IDsAdded (15)
|
Brings in #535 (transaction-control gate, paging probe, workspace editor storage) and keeps both sides' additions to the @foxschema/sql and @foxschema/ui-shared export lists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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: 346a1dd8-bed4-4ce7-981f-d28d7f8a2606) |
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.
Three pieces of SQL Editor work, plus a cleanup pass over all of it. Also carries the unpushed
fix(access)commit, whose branch was already merged as #534.What changed
Clause-aware completions.
completionSlotreads the clause touching the caret and offers the next kind of name: tables (each with a suggested alias) afterFROM/JOIN,JOINafterLEFT/INNER/OUTER, andalias.columnplus common SQL functions afterON/WHERE/AND. A space after one of those keywords opens the popup — Monaco suppresses trigger characters on its own whenever quick suggestions are on, so this needs anonDidTypehandler. The slim editor build also had to importsuggestController; without it completion providers register and never appear.Multi-row Data Peek filters. Several
WHEREconditions joined withAND, and anORDER BYlist with a direction per column.Shared workspace scripts (migration 31, append-only). SQL stored on the server rather than in the browser, so every member of a workspace opens the same text. Viewers read them; editors and owners save and delete.
Password-manager fix. Signing in on this origin teaches Chrome the site has a login, after which Enter in Monaco's textarea asked macOS to unlock saved passwords. The textarea is now marked so that does not happen.
Cleanup applied over the above
splitPeekListre-implementedsplitSelectItems— whichtablePreview.tsalready imports on line 17, and which both CLAUDE.md and CODE_MAP.md say not to duplicate. Generalised the existing scanner tosplitTopLevel(text, sep)and deleted the copy. This also closes a real gap: the copy tracked only'and", so a MySQL`a,b`or SQL Server[a,b]column split mid-identifier.isInFromTablePosition—completionSlotreplaced it, and it had no caller left but its own test (which this change was still editing).completion.ts: one keyword table now drives the word set, the scan regex and the slot lookup;buildTableIndexis lazy instead of rebuilt on every keystroke (and was being rebuilt inside a per-alias loop);qualifiedTableNameis a map lookup instead of an O(tables²) rescan per suggested table; the literal-stripping pass runs once per keystroke instead of twice.apply()instead of inlining it with a duplicated limit-parsing IIFE; one helper builds the per-row test ids.runScriptOpreplaces two identical async handlers and resets the busy flag infinally; a save no longer refetches what the POST already returned.AccessReportuses the report's ownroleCountagain, so "how many of these are roles" has one definition instead of two.Reviewer notes
/api/workspaces/scriptsroutes were never declared inhttp-contract.test.ts, andsql-editor-join-typing.test.tswas absent fromrun-all.mjs, so it would never have run.apps/webtypecheck was failing ononDidType, which is on Monaco'sICodeEditorbut not in the publiceditor.apitypings. It is now reached through one narrow cast, and the string-keyedgetContribution('editor.contrib.suggestController')cast was replaced with the supportededitor.trigger('keyboard', 'editor.action.triggerSuggest', { auto: true }).WorkspaceScripts.roleIn()queriesworkspace_membersdirectly and hardcodesrole === 'editor' || 'owner', rather than going throughWorkspaceDirectory.require()like every other workspace service. That skips three layers those services apply: the archived-workspace rejection, theappRole === 'admin'override, and the RBACrole_permissionsoverlay. Concretely — scripts stay readable and writable in an archived workspace, an app admin who is not a member getsnot_found, and re-granting permissions in the Access UI does not reach scripts. Left as-is deliberately: changing an authorization gate is a decision, not a cleanup.monaco-editor/editor/contrib/...import reaches into the library's internals on purpose — it is the same path Monaco's owneditor.main.jsuses, and importingeditor.maininstead would pull all ~90 languages and blow the 240 KB first-load budget.Gates
cd apps/web && npx tsc --noEmit— clean (was failing)npx vitest run— 6306 passed, 0 failed, 1 expected fail, 137 skipped (was 2 failing)npm run test-ids— regenerated; 996 controls. This also fixed a malformed catalog entry:data-peek-order-clear-{id}{index}was shaped differently from its three siblings, producing a${string}${string}type and a useless two-arg accessor.E2E not run — the new Playwright suite needs the seeded dialect containers.
🤖 Generated with Claude Code
Note
Medium Risk
Adds persisted workspace scripts and broad SQL completion behavior changes; script authorization uses direct workspace-member roles rather than the shared
WorkspaceDirectory.require()path used elsewhere.Overview
SQL Editor gets clause-aware autocomplete: suggestions follow context after
FROM/JOIN, join modifiers (LEFT→JOIN/OUTER), and expressions (ON/WHERE/=→alias.columnand common functions). Completions prefer the Select schema connection, auto-open on space/=viaonDidType, and load Monaco’s suggest controller so the widget actually appears. Chrome password prompts in the editor are suppressed viaone-time-codeon the Monaco textarea.Data Peek filters are multi-row: several WHERE predicates (AND) and ORDER BY columns with per-column ASC/DESC, backed by new
splitPeekWhere/splitPeekOrderhelpers on sharedsplitTopLevel.Workspace scripts are new server-side shared SQL (migration
workspace_scripts,GET/POST/DELETE /api/workspaces/scripts). The sidebar Scripts panel adds a Workspace tab to save, open, and delete scripts (editors/owners write; viewers read). The workspace switcher is now a select instead of a list of buttons.Access renames the former Diff tab and panel copy to Insight. The access report role count only counts roles that appear in the report rows (fixes misleading totals on Db2).
Tests and e2e wiring add join-typing coverage, peek filter tests, http-contract entries for script routes, and regenerated test IDs.
Reviewed by Cursor Bugbot for commit 151fe83. Bugbot is set up for automated code reviews on this repo. Configure here.