MonacoEditor() — supabase Function Reference
Architecture documentation for the MonacoEditor() function in MonacoEditor.tsx from the supabase codebase.
Entity Profile
Dependency Diagram
graph TD 7314d59d_471f_cfe1_1fae_6dc8c5a6d203["MonacoEditor()"] 2bdac7e5_a25b_6415_051d_1503de098a7f["createSqlSnippetSkeletonV2()"] 7314d59d_471f_cfe1_1fae_6dc8c5a6d203 -->|calls| 2bdac7e5_a25b_6415_051d_1503de098a7f style 7314d59d_471f_cfe1_1fae_6dc8c5a6d203 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx lines 40–287
const MonacoEditor = ({
id,
snippetName,
editorRef,
monacoRef,
autoFocus = true,
placeholder = '',
className,
executeQuery,
onHasSelection,
onPrompt,
onMount,
}: MonacoEditorProps) => {
const router = useRouter()
const { profile } = useProfile()
const { ref, content } = useParams()
const { data: project } = useSelectedProjectQuery()
const snapV2 = useSqlEditorV2StateSnapshot()
const tabsSnap = useTabsStateSnapshot()
const aiSnap = useAiAssistantStateSnapshot()
const { openSidebar, toggleSidebar } = useSidebarManagerSnapshot()
const [intellisenseEnabled] = useLocalStorageQuery(
LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE,
true
)
const [isAIAssistantHotkeyEnabled] = useLocalStorageQuery<boolean>(
LOCAL_STORAGE_KEYS.HOTKEY_SIDEBAR(SIDEBAR_KEYS.AI_ASSISTANT),
true
)
// [Joshen] Lodash debounce doesn't seem to be working here, so opting to use useDebounce
const [value, setValue] = useState('')
const debouncedValue = useDebounce(value, 1000)
const snippet = snapV2.snippets[id]
const disableEdit =
snippet?.snippet.visibility === 'project' && snippet?.snippet.owner_id !== profile?.id
const executeQueryRef = useRef(executeQuery)
executeQueryRef.current = executeQuery
const handleEditorOnMount: OnMount = async (editor, monaco) => {
editorRef.current = editor
monacoRef.current = monaco
const model = editorRef.current.getModel()
if (model !== null) {
monacoRef.current.editor.setModelMarkers(model, 'owner', [])
}
editor.addAction({
id: 'run-query',
label: 'Run Query',
keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.Enter],
contextMenuGroupId: 'operation',
contextMenuOrder: 0,
run: () => {
executeQueryRef.current()
},
})
editor.addAction({
id: 'save-query',
label: 'Save Query',
keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.KeyS],
contextMenuGroupId: 'operation',
contextMenuOrder: 0,
run: () => {
if (snippet) snapV2.addNeedsSaving(snippet.snippet.id)
},
})
editor.addAction({
id: 'explain-code',
label: 'Explain Code',
contextMenuGroupId: 'operation',
contextMenuOrder: 1,
run: () => {
const selectedValue = (editorRef?.current as any)
.getModel()
.getValueInRange((editorRef?.current as any)?.getSelection())
openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
aiSnap.newChat({
name: 'Explain code section',
sqlSnippets: [selectedValue],
initialInput: 'Can you explain this section to me in more detail?',
})
},
})
editor.addAction({
id: 'toggle-ai-assistant',
label: 'Toggle AI Assistant',
keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.KeyI],
run: () => {
if (isAIAssistantHotkeyEnabled) {
toggleSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
}
},
})
if (onPrompt) {
editor.addAction({
id: 'generate-sql',
label: 'Generate SQL',
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK],
run: () => {
const selection = editor.getSelection()
const model = editor.getModel()
if (!model || !selection) return
const allLines = model.getLinesContent()
const startLineIndex = selection.startLineNumber - 1
const endLineIndex = selection.endLineNumber
const beforeSelection = allLines.slice(0, startLineIndex).join('\n') + '\n'
const selectedText = allLines.slice(startLineIndex, endLineIndex).join('\n')
const afterSelection = '\n' + allLines.slice(endLineIndex).join('\n')
onPrompt({
selection: selectedText,
beforeSelection,
afterSelection,
startLineNumber: selection?.startLineNumber ?? 0,
endLineNumber: selection?.endLineNumber ?? 0,
})
},
})
}
editor.onDidChangeCursorSelection(({ selection }) => {
const noSelection =
selection.startLineNumber === selection.endLineNumber &&
selection.startColumn === selection.endColumn
onHasSelection(!noSelection)
})
if (autoFocus) {
if (editor.getValue().length === 1) editor.setPosition({ lineNumber: 1, column: 2 })
editor.focus()
}
onMount?.(editor)
}
function handleEditorChange(value: string | undefined) {
tabsSnap.makeActiveTabPermanent()
if (id && value) {
if (!snippet && ref && profile !== undefined && project !== undefined) {
const snippet = createSqlSnippetSkeletonV2({
idOverride: id,
name: snippetName,
sql: value,
owner_id: profile?.id,
project_id: project?.id,
})
snapV2.addSnippet({ projectRef: ref, snippet })
router.push(`/project/${ref}/sql/${snippet.id}`, undefined, { shallow: true })
}
setValue(value)
}
}
useEffect(() => {
if (debouncedValue.length > 0 && snippet) {
const shouldInvalidate = snippet.snippet.isNotSavedInDatabaseYet
snapV2.setSql({ id, sql: value, shouldInvalidate })
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedValue])
// if an SQL query is passed by the content parameter, set the editor value to its content. This
// is usually used for sending the user to SQL editor from other pages with SQL.
useEffect(() => {
if (content && content.length > 0) handleEditorChange(content)
}, [])
return (
<>
{disableEdit && (
<Admonition
type="default"
className="rounded-none border-0 border-b"
title="Read-only snippet"
description="This snippet has been shared to the project and is only editable by the owner who created this snippet. You may duplicate this snippet into a personal copy by right clicking on the snippet and selecting “Duplicate query”."
/>
)}
<Editor
className={cn(className, 'monaco-editor')}
theme={'supabase'}
onMount={handleEditorOnMount}
onChange={handleEditorChange}
defaultLanguage="pgsql"
defaultValue={snippet?.snippet.content?.sql}
path={id}
options={{
tabSize: 2,
fontSize: 13,
placeholder,
lineDecorationsWidth: 0,
readOnly: disableEdit,
minimap: { enabled: false },
wordWrap: 'on',
padding: { top: 4 },
// [Joshen] Commenting the following out as it causes the autocomplete suggestion popover
// to be positioned wrongly somehow. I'm not sure if this affects anything though, but leaving
// comment just in case anyone might be wondering. Relevant issues:
// - https://github.com/microsoft/monaco-editor/issues/2229
// - https://github.com/microsoft/monaco-editor/issues/2503
// fixedOverflowWidgets: true,
suggest: {
showMethods: intellisenseEnabled,
showFunctions: intellisenseEnabled,
showConstructors: intellisenseEnabled,
showDeprecated: intellisenseEnabled,
showFields: intellisenseEnabled,
showVariables: intellisenseEnabled,
showClasses: intellisenseEnabled,
showStructs: intellisenseEnabled,
showInterfaces: intellisenseEnabled,
showModules: intellisenseEnabled,
showProperties: intellisenseEnabled,
showEvents: intellisenseEnabled,
showOperators: intellisenseEnabled,
showUnits: intellisenseEnabled,
showValues: intellisenseEnabled,
showConstants: intellisenseEnabled,
showEnums: intellisenseEnabled,
showEnumMembers: intellisenseEnabled,
showKeywords: intellisenseEnabled,
showWords: intellisenseEnabled,
showColors: intellisenseEnabled,
showFiles: intellisenseEnabled,
showReferences: intellisenseEnabled,
showFolders: intellisenseEnabled,
showTypeParameters: intellisenseEnabled,
showIssues: intellisenseEnabled,
showUsers: intellisenseEnabled,
showSnippets: intellisenseEnabled,
},
}}
/>
</>
)
}
Domain
Subdomains
Source
Frequently Asked Questions
What does MonacoEditor() do?
MonacoEditor() is a function in the supabase codebase.
What does MonacoEditor() call?
MonacoEditor() calls 1 function(s): createSqlSnippetSkeletonV2.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free