## Context
Related to Notebooks/Explorers - this one's just shifting files from the
SQLEditor into more generic folders from a file organization POV, such
that files under the Explorer folder have no dependency on files within
the SQLEditor folder
Mainly
- UtilityTabResults.utils: `getSqlErrorLines`
- Moved into `data/sql/utils.ts`
- SQLEditor.utils: `applyAutoLimit`, `getSqlErrorLines`,
`trimTrailingSemicolons`
- Moved into `data/sql/utils.ts`
- SQLEditor/UtilityPanel: `ResultCell`, `Results`, `CellDetailPanel`
- Moved into `components/ui/DataGridResults`
- Also shifted corresponding tests over here
- Also addressed some `any` type casts
## To test
- Just need to ensure that the SQL Editor still works as expected
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Standardized query results across the Studio with a shared data grid.
* Improved result-table formatting, column sizing, clipboard handling,
and large-value display.
* Added safer automatic row limits for eligible SQL queries.
* Centralized SQL error display and formatting utilities.
* **Refactor**
* Improved type safety for query rows and cell values.
* **Tests**
* Added comprehensive coverage for result-grid and SQL utility behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
When a user has sorted by some column in the Table Editor and the column
is deleted, the sort data is wrong so it causes issues. In the general
view in the Table Editor, the error is handled by removing the sort key
when a specific error is detected but it can still happen in
ForeignRowSelector.
To test:
1. Have 2 tables with references between them.
2. In the `sessionStorage`, under the `supabase_grid-<ref>` key, update
the sort key to a non-existant column for a table.
3. Try to open the `ForeignRowSelector` for that table by clicking on a
cell in the referencing column.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Sorting now validates referenced columns and ignores invalid sort
entries.
* Local sort restoration and UI sort application now derive sorts from
the original table context for more consistent behavior across editors
and popovers.
* Prefetch logic uses the resolved table context when falling back to
saved sorts.
* **Tests**
* Added cases for malformed and out-of-scope sort parameters to prevent
regressions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
- Noticing our code we have many patterns of calling localstorage and
handling those errors
- We should add those in a single well tested file
- Handle those errors in the singleton which makes it easier for us to
debug customer issues. Logger is outputing local storage warnings for
feature we expose
- Side effect of this is random crashes on studio when local storage
isn't available or handled correctly
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved browser storage handling across the app for more reliable
persistence and graceful behavior in restricted or non-browser
environments (settings, previews, charts, tabs, sign-in/session flows,
integrations, and UI state).
* **New Features**
* Introduced a safe storage layer to standardize and harden
local/session persistence.
* **Tests**
* Added comprehensive tests covering the new safe storage behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Bug fix.
## What is the current behavior?
- Safari Table Editor cells fail to copy from a focused cell with `⌘C`.
- Safari right-click can show the browser menu instead of the custom
cell menu.
- Copy can leave RDG's copied-cell fill behind.
## What is the new behavior?
- Reuses the existing shared `copyToClipboard(value, onSuccess)`
pattern, with the Safari clipboard fix inside that util.
- Handles selected-cell `⌘C` in the RDG keydown path, preventing
browser/RDG defaults and showing the success toast only after copy.
- Replaces the row-level synthetic context-menu shim with RDG's
`onCellContextMenu`, so we prevent Safari's browser menu at the source
and select/focus the target cell.
- Keeps the selected-cell outline while the controlled menu is open.
## Additional context
- `RowRenderer` was only supporting the old context-menu shim; removing
it is part of moving to RDG's cell event path.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Context menu now provides feedback with toast notifications when
copying cells or rows.
* Selected cells retain their visual styling when context menu is open.
* **Bug Fixes**
* Improved keyboard shortcut handling for copy functionality.
* Enhanced clipboard error handling with user-friendly error messages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## TL;DR
typing into a cell after single click was broken for keys like `I`, `F`,
`C`,`R`, `U` & `S`
because those keys could be picked up as shortcut prefixes instead of
starting cell editing
## sol:
https://github.com/user-attachments/assets/e388b79f-5334-47ef-a834-9164b255b88c
## ref:
- Closes https://github.com/supabase/supabase/issues/45445
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved keyboard interaction in grid cells: typing a single printable
character now enters editable cells directly (allowing immediate
edit-mode), while other registered keyboard shortcuts still take
precedence and continue to block default grid behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Feature — a set of new keyboard shortcuts for the table editor, along
with infrastructure to register, gate, and surface them.
## What is the current behavior?
Clicking into the grid "traps" the keyboard: Escape doesn't pop out,
there are no shortcuts for row selection / deletion / navigation, and
the search-tables input grabs focus on page load.
## What is the new behavior?
### New shortcuts (all scoped to the table editor)
| Keybind | Action | Surface |
|---|---|---|
| `Esc` | Exit grid selection — clears the highlighted cell and drops
focus back to the page | hotkey |
| `↑` / `↓` | Start grid navigation from the first cell when no cell is
selected | hotkey |
| `Shift+Space` | Toggle selection on the current row | hotkey +
checkbox tooltip |
| `Mod+A` | Toggle selection on all displayed rows (matches Excel) |
hotkey + header-checkbox tooltip + Cmd+K |
| `Mod+Shift+A` | Toggle selection on all rows in the table | hotkey +
"Select all rows in table" button tooltip + Cmd+K |
| `Mod+Backspace` | Delete selected rows | hotkey + delete-button
tooltip + Cmd+K |
### Infrastructure
- **Split registry** — table-editor shortcuts moved to
`state/shortcuts/registry/table-editor.ts`, spread into `SHORTCUT_IDS`.
Makes it easy to scope a runtime check to a specific surface.
- **`eventMatchesAnyShortcut`** (`state/shortcuts/matchEvent.ts`) —
queries the hotkey library's live `SequenceManager` so gated shortcuts
(`enabled: false`) are correctly excluded. Covered by
`matchEvent.test.ts`.
- **`handleCellKeyDown`** now calls `event.preventGridDefault()`
whenever the keystroke matches an active table-editor shortcut, so rdg's
"start editing on key press" default doesn't compete with shortcut
actions (e.g. typing `Shift+X` no longer opens edit mode with `X` as
input).
- **`<Shortcut>` / `<ShortcutTooltip>`** used on the header checkbox,
the per-row checkbox, the "Select all rows in table" button, and the
delete button — keybinds show up on hover (Linear-style) so users can
discover them without reading docs.
- **CSS** — `.rdg:not(:focus-within) .rdg-cell[aria-selected='true']`
drops the selected-cell outline whenever focus leaves the grid,
reinforcing the "you're out" feedback after `Esc`.
- **`useShortcut`** wraps the Cmd+K-registered action to close the
command menu after firing (previously menu stayed open after selecting
an action).
- **Search-tables input** no longer auto-focuses on load, so arrow
shortcuts work immediately without clicking out first.
## Additional context
Linear: FE-3057
### Test plan
- [x] Open any table → `↓` selects the first cell; subsequent arrows
navigate rows
- [x] `Esc` drops focus out of the grid and re-enables `↓` to re-enter
- [x] Click a cell → `Shift+Space` toggles that row's selection
(checkbox)
- [x] `Mod+A` toggles all displayed rows
- [x] With pagination + some rows selected → `Mod+Shift+A` toggles
"Select all rows in table"
- [x] With rows selected → `Mod+Backspace` deletes them (existing
confirmation flow)
- [x] Hover the header checkbox / per-row checkbox / delete button →
keybind tooltip after ~500ms
- [x] Cmd+K with selection → the relevant action shows up; selecting it
closes the palette and runs
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added table editor keyboard shortcuts for navigation, row selection,
and cell actions, with command-menu integration and visible shortcut
tooltips.
* **Improvements**
* Better keyboard handling in grid cells allowing external shortcuts to
override default behavior.
* Select-all/deselect-all toggle and improved select-row UX;
selected-cell styling no longer shows when grid loses focus.
* Command menu now reliably closes before executing shortcut actions.
* Removed autofocus on the table editor search input for consistent
focus behavior.
* **Tests**
* Added unit tests covering shortcut matching and command-menu shortcut
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Context
If you've got a queued operation on a table, then switch tables, the
dashboard stalls for a few seconds before finally rendering the selected
table.
This was caused by an infinite loop in a useEffect calling
`reapplyOptimisticUpdates` due to `dataUpdatedAt` being in the
dependency array (which comes from react query)
Removing `dataUpdatedAt` would resolve the issue, but then it won't
solve the following comment in the code:
`// This ensures pending changes remain visible when switching tabs or
after data refresh`
## Changes involved
Opting to refactor the logic for rendering data in the Grid instead
- Avoid manipulating the data directly from the query client
- Manual changes to the query client are hard to track when debugging
- Ideally the data in the query client are exactly what is coming from
the API
- Instead just compute the row data if there's operations applied, and
render that in the grid
```
const baseRows = data?.rows ?? EMPTY_ARR
const rows = formatGridDataWithOperationValues({ operations, rows:
baseRows })
```
- Simplifies operations logic + data in react query remains as the
source of truth
- This also improves perceived performance, as previously we'd need to
invalidate the query client if we're removing any operation.
- A lot more apparent with the undo operation introduced
[here](https://github.com/supabase/supabase/pull/43957)
- Whereas now, we'll just revert back to whatever's in the query client
(and still do the invalidation behind the scenes) so things feel faster
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Refactor
## What is the current behavior?
`/incident-status` is handled via Pages Router.
## What is the new behavior?
`/incident-status` is handled via App Router, enabling use of Vercel
Data Cache to cache the upstream fetch.
## Additional context
Adding the first App Router route handler triggered `next typegen` (run
as `pretypecheck`) to generate `.next/dev/types/validator.ts`, which
imports all route files and expanded the type-checked graph. This
surfaced pre-existing `null`-safety errors in:
- `components/grid/SupabaseGrid.utils.ts` — `useSearchParams()` result
- `components/layouts/ProjectLayout/UpgradingState/index.tsx` —
`useSearchParams()` result
- `pages/project/[ref]/sql/quickstarts.tsx` — `useParams()` result
- `pages/project/[ref]/sql/templates.tsx` — `useParams()` result
These are fixed with optional chaining. The `tsconfig.json` change
(adding `.next/dev/types/**/*.ts` to `include`) is auto-generated by
Next.js and committed as correct behavior.
* Possible solution with building the URL from local storage.
* Refactor the local storage for tabs to use table ids.
* Fix the saving table state to local storage.
* Minor fixes.
* Open the correct schema when following the link.
* Minor fixes from CodeRabbit.
* Address charis' feedbacks
* Clean
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Exporting all rows (in CSV, SQL, or JSON format) currently uses offset pagination, which can cause performance problems if the table is large. There is also a correctness problem if the table is being actively updated as the export happens, because the relative row offsets could shift between queries.
Now that composite filters are available in postgres-meta, we can change to using cursor pagination on the primary key (or any non-null unique keys) wherever possible. Where this is not possible, the user will be shown a confirmation dialog explaining the possible performance impact.
---------
Co-authored-by: Ali Waseem <waseema393@gmail.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
* Improve stability and explicitness of table editor tab cache <-> url syncing
* fix: maintain filter state when using nav bar to switch back to Table Editor
---------
Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
* Remove useKeyboardShortcuts in Results.tsx
* Remove Cmd C overrides in table editor
* Refactor onCellKeydown to a common utils, and add check for ctrlKey
* chore: remove react-tracked part 1
* move out table specific state to own store
* chore: remove react-tracked part 2
* remove unused type
* ensure table is properly updated on changes
* remove all filters save in local storage
* Tiny fixes
* fix sort / filters applying issue + feedback
* fix entity links
* remove unnecessary style
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
* Fix tests in tests/unit, tests/components and files under tests, looking into tests/pages
* Fix tests under pages/projects root
* Fix
* Comment out broken tests that im stuck with
* Fix api-report.test
* Fix storage-report-test
* chore: fix some tests
* chore: remove logging
* Fix LogsPreviewer.test.js
* Fix most of logs-query-test
* Skip broken tests instead of false positiving them
---------
Co-authored-by: TzeYiing <ty@tzeyiing.com>
* Replace all methods of MetaStore with react queries.
* Remove unneeded usages of MetaStore.
* Remove RootStore completely. The only thing left from these stores is uiStore.
* Remove unnecessary comments.
* Delete MetaStore.
* Fix the usage of the wrong toaster.
* Remove unused variables
* Remove onSqlQuery
* Convert some ui setNotification calls to direct toast calls
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
* Do up logic for callback for opening side panel
* Add TextEditor side panel and fix some quirky bugs with JSONEditor too
* Add Markdown Preview in TextEditor
* Fix bad cs
* Fix border css
* Add react-query mutations for columns APIs.
* Use the new delete column mutation.
* Remove the column store and replace all its methods with mutations from react-query.
* Fix type errors.
* Move some the meta store methods to be pure functions in sidepanel.utils.
* Move the createColumn and updateColumn out of the metaStore.
* Some refactors and fixes
* Shift query invalidation when deleting column to mutation file instead of component file
* reorder some code for my sanity
* remove some @ts-ignores
* remove more @ts-ignores
* Update apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.utils.ts
* Fix ForeignKeyFormatter crashing client
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Alaister Young <a@alaisteryoung.com>
Co-authored-by: Alaister Young <alaister@users.noreply.github.com>
* Move all studio files from /studio to /apps/studio.
* Move studio specific prettier ignores.
* Fix the ui references from studio.
* Fix the css imports.
* Fix all package.json issues.
* Fix the prettier setup for the studio app.
* Add .turbo folder to prettierignore.
* Fix the github workflows.