Files
supabase/packages/common/constants/local-storage.ts
Joshen Lim 0b97e0ff86 Joshen/fe 2642 project settings allow to select a replica to power (#43626)
## Context

Related to dashboard scalability
Previous PR: https://github.com/supabase/supabase/pull/42856

Note: Changes are all feature flagged still and I'm still not entirely
convinced with the current UX
Will iterate as as go along, and only make this publicly available when
we're satisfied with the behaviour

Adds a "Dashboard preference" section to the project settings
<img width="265" height="740" alt="image"
src="https://github.com/user-attachments/assets/6ce1aa19-26c2-47c6-a9c4-595137266631"
/>

In which users can then select which database they'd like to use for
read queries run from the dashboard
Note: Everything is local storage for now, but we'd need middleware
support if we want to make this setting persist for all users on the
project
<img width="791" height="434" alt="image"
src="https://github.com/user-attachments/assets/e651d6d9-fed4-4da4-b552-c9f93f8d46d3"
/>

Added a dialog as well to further explain what this implies
<img width="610" height="312" alt="image"
src="https://github.com/user-attachments/assets/0aa957af-cb51-476f-aa79-8948a7cbe5ae"
/>

## To test

- Choosing a replica in dashboard preferences will only affect the table
editor as thats the only place that's set up so far to use a replica for
read queries (I'll need to follow up for other parts of the dashboard in
subsequent PRs)
2026-03-12 11:18:28 +07:00

168 lines
7.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export const LOCAL_STORAGE_KEYS = {
/**
* STUDIO
*/
AI_ASSISTANT_STATE: (projectRef: string | undefined) =>
`supabase-ai-assistant-state-${projectRef}`,
SIDEBAR_BEHAVIOR: 'supabase-sidebar-behavior',
EDITOR_PANEL_STATE: 'supabase-editor-panel-state',
PROJECTS_VIEW: 'projects-view',
PROJECTS_FILTER: 'projects-filter',
PROJECTS_SORT: 'projects-sort',
FEEDBACK_WIDGET_CONTENT: 'feedback-widget-content',
FEEDBACK_WIDGET_SCREENSHOT: 'feedback-widget-screenshot',
INCIDENT_BANNER_DISMISSED_IDS: 'incident-banner-dismissed-ids',
MAINTENANCE_BANNER_DISMISSED: (id: string) => `maintenance-banner-dismissed-${id}`,
DASHBOARD_PREFERENCES: (ref: string) => `dashboard-preferences-${ref}`,
UI_PREVIEW_API_SIDE_PANEL: 'supabase-ui-api-side-panel',
UI_PREVIEW_CLS: 'supabase-ui-cls',
UI_PREVIEW_INLINE_EDITOR: 'supabase-ui-preview-inline-editor',
UI_PREVIEW_UNIFIED_LOGS: 'supabase-ui-preview-unified-logs',
UI_ONBOARDING_NEW_PAGE_SHOWN: 'supabase-ui-onboarding-new-page-shown',
UI_PREVIEW_BRANCHING_2_0: 'supabase-ui-branching-2-0',
UI_PREVIEW_ADVISOR_RULES: 'supabase-ui-advisor-rules',
UI_PREVIEW_QUEUE_OPERATIONS: 'supabase-ui-queue-operations',
UI_PREVIEW_TABLE_FILTER_BAR: 'supabase-ui-table-filter-bar',
UI_PREVIEW_PG_DELTA_DIFF: 'supabase-ui-pg-delta-diff',
UI_PREVIEW_PLATFORM_WEBHOOKS: 'supabase-ui-platform-webhooks',
NEW_LAYOUT_NOTICE_ACKNOWLEDGED: 'new-layout-notice-acknowledge',
TABS_INTERFACE_ACKNOWLEDGED: 'tabs-interface-acknowledge',
AI_ASSISTANT_MCP_OPT_IN: 'ai-assistant-mcp-opt-in',
DASHBOARD_HISTORY: (ref: string) => `dashboard-history-${ref}`,
STORAGE_PREFERENCE: (ref: string) => `storage-explorer-${ref}`,
AUTH_USERS_FILTER: (ref: string) => `auth-users-filter-${ref}`,
AUTH_USERS_SORT_BY_VALUE: (ref: string) => `auth-users-sort-by-value-${ref}`,
AUTH_USERS_COLUMNS_CONFIGURATION: (ref: string) => `supabase-auth-users-columns-${ref}`,
AUTH_USERS_IMPROVED_SEARCH_DISMISSED: (ref: string) =>
`auth-users-improved-search-dismissed-${ref}`,
SQL_EDITOR_INTELLISENSE: 'supabase_sql-editor-intellisense-enabled',
SQL_EDITOR_SPLIT_SIZE: 'supabase_sql-editor-split-size',
// Key to track which schemas are ok to be sent to AI. The project ref is intentionally put at the end for easier search in the browser console.
SQL_EDITOR_AI_SCHEMA: (ref: string) => `supabase_sql-editor-ai-schema-enabled-${ref}`,
SQL_EDITOR_AI_OPEN: 'supabase_sql-editor-ai-open',
SQL_EDITOR_LAST_SELECTED_DB: (ref: string) => `sql-editor-last-selected-db-${ref}`,
SQL_EDITOR_SQL_BLOCK_ACKNOWLEDGED: (ref: string) => `sql-editor-sql-block-acknowledged-${ref}`,
SQL_EDITOR_SECTION_STATE: (ref: string) => `sql-editor-section-state-${ref}`,
SQL_EDITOR_SORT: (ref: string) => `sql-editor-sort-${ref}`,
// Key to track if the user has acknowledged the security notifications preview
SECURITY_NOTIFICATIONS_ACKNOWLEDGED: (ref: string) =>
`security-notifications-acknowledged-${ref}`,
LOG_EXPLORER_SPLIT_SIZE: 'supabase_log-explorer-split-size',
GRAPHIQL_RLS_BYPASS_WARNING: 'graphiql-rls-bypass-warning-dismissed',
CLS_DIFF_WARNING: 'cls-diff-warning-dismissed',
CLS_SELECT_STAR_WARNING: 'cls-select-star-warning-dismissed',
QUERY_PERF_SHOW_BOTTOM_SECTION: 'supabase-query-perf-show-bottom-section',
LINTER_SHOW_FOOTER: 'supabase-linter-show-footer',
// Key to track account deletion requests
ACCOUNT_DELETION_REQUEST: 'supabase-account-deletion-request',
// Used for storing a user id when sending reports to Sentry. The id is hashed for anonymity.
SENTRY_USER_ID: 'supabase-sentry-user-id',
// Used for storing the last sign in method used by the user
LAST_SIGN_IN_METHOD: 'supabase-last-sign-in-method',
// Key to track the last selected schema. The project ref is intentionally put at the end for easier search in the browser console.
LAST_SELECTED_SCHEMA: (ref: string) => `last-selected-schema-${ref}`,
// Track position of nodes for schema visualizer
SCHEMA_VISUALIZER_POSITIONS: (ref: string, schemaId: number) =>
`schema-visualizer-positions-${ref}-${schemaId}`,
// Used for allowing the main nav panel to expand on hover
EXPAND_NAVIGATION_PANEL: 'supabase-expand-navigation-panel',
GITHUB_AUTHORIZATION_STATE: 'supabase-github-authorization-state',
// Notice banner keys
FLY_POSTGRES_DEPRECATION_WARNING: 'fly-postgres-deprecation-warning-dismissed',
API_KEYS_FEEDBACK_DISMISSED: (ref: string) => `supabase-api-keys-feedback-dismissed-${ref}`,
MAINTENANCE_WINDOW_BANNER: 'maintenance-window-banner-2026-01-16',
REPORT_DATERANGE: 'supabase-report-daterange',
// api keys view switcher for new and legacy api keys
API_KEYS_VIEW: (ref: string) => `supabase-api-keys-view-${ref}`,
LAST_VISITED_ORGANIZATION: 'last-visited-organization',
// user impersonation selector previous searches
USER_IMPERSONATION_SELECTOR_PREVIOUS_SEARCHES: (ref: string) =>
`user-impersonation-selector-previous-searches-${ref}`,
HOTKEY_COMMAND_MENU: 'supabase-dashboard-hotkey-command-menu',
LAST_OPENED_SIDE_BAR: (ref: string) => `last-opened-sidebar-${ref}`,
// Project sidebar hotkeys
HOTKEY_SIDEBAR: (sidebarId: string) => `supabase-dashboard-hotkey-sidebar-${sidebarId}`,
// Index Advisor notice dismissed
INDEX_ADVISOR_NOTICE_DISMISSED: (ref: string) => `index-advisor-notice-dismissed-${ref}`,
// RLS event trigger banner dismissed
RLS_EVENT_TRIGGER_BANNER_DISMISSED: (ref: string) => `rls-event-trigger-banner-dismissed-${ref}`,
// Observability banner dismissed
OBSERVABILITY_BANNER_DISMISSED: (ref: string) => `observability-banner-dismissed-${ref}`,
// Tax ID banner dismissed
TAX_ID_BANNER_DISMISSED: (slug: string) => `tax-id-banner-dismissed-${slug}`,
TABLE_EDITOR_NEW_FILTER_BANNER_DISMISSED: (ref: string) =>
`table-editor-new-filter-banner-dismissed-${ref}`,
/**
* COMMON
*/
/** @deprecated – we're using usercentrics instead to handle telemetry consent */
TELEMETRY_CONSENT: 'supabase-consent-ph',
TELEMETRY_DATA: 'supabase-telemetry-data',
/**
* DOCS
*/
SAVED_ORG: 'docs.ui.user.selected.org',
SAVED_PROJECT: 'docs.ui.user.selected.project',
SAVED_BRANCH: 'docs.ui.user.selected.branch',
HIDE_PROMO_TOAST: 'supabase-hide-promo-toast-lw15-ticket',
/**
* WWW
*/
BLOG_VIEW: 'supabase-blog-view',
} as const
export type LocalStorageKey = (typeof LOCAL_STORAGE_KEYS)[keyof typeof LOCAL_STORAGE_KEYS]
const LOCAL_STORAGE_KEYS_ALLOWLIST = [
'graphiql:theme',
'theme',
'supabaseDarkMode',
'supabase.dashboard.auth.debug',
'supabase.dashboard.auth.navigatorLock.disabled',
LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT,
LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL,
LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR,
LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS,
LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS,
LOCAL_STORAGE_KEYS.UI_PREVIEW_QUEUE_OPERATIONS,
LOCAL_STORAGE_KEYS.UI_PREVIEW_TABLE_FILTER_BAR,
LOCAL_STORAGE_KEYS.UI_PREVIEW_PLATFORM_WEBHOOKS,
LOCAL_STORAGE_KEYS.LAST_SIGN_IN_METHOD,
LOCAL_STORAGE_KEYS.HIDE_PROMO_TOAST,
LOCAL_STORAGE_KEYS.BLOG_VIEW,
LOCAL_STORAGE_KEYS.AI_ASSISTANT_MCP_OPT_IN,
LOCAL_STORAGE_KEYS.UI_PREVIEW_BRANCHING_2_0,
LOCAL_STORAGE_KEYS.LINTER_SHOW_FOOTER,
LOCAL_STORAGE_KEYS.SIDEBAR_BEHAVIOR,
]
export function clearLocalStorage() {
for (const key in localStorage) {
if (!LOCAL_STORAGE_KEYS_ALLOWLIST.includes(key)) {
localStorage.removeItem(key)
}
}
}