From 03568178a4316cc33329f217df50944673dedd4f Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Fri, 8 Dec 2023 15:20:33 +0100 Subject: [PATCH] feat: sql types autocomplete (#2810) * feat: sql types autocomplete * fix: frontend check --- frontend/src/lib/components/Editor.svelte | 75 +++++++++- .../src/lib/components/ScriptEditor.svelte | 2 +- .../src/lib/components/WorkspaceGroup.svelte | 4 +- .../editor/componentsPanel/CssProperty.svelte | 2 - .../editor/componentsPanel/CssSettings.svelte | 1 - .../componentsPanel/ThemeCodePreview.svelte | 1 - .../InlineScriptEditor.svelte | 2 +- .../flows/content/FlowModuleComponent.svelte | 4 +- frontend/src/lib/consts.ts | 132 ++++++++++++++++++ 9 files changed, 208 insertions(+), 15 deletions(-) diff --git a/frontend/src/lib/components/Editor.svelte b/frontend/src/lib/components/Editor.svelte index f260f67075..64b89f40ce 100644 --- a/frontend/src/lib/components/Editor.svelte +++ b/frontend/src/lib/components/Editor.svelte @@ -44,7 +44,7 @@ import type { DocumentUri, MessageTransports } from 'vscode-languageclient' import { buildWorkerDefinition } from './build_workers' import { workspaceStore } from '$lib/stores' - import { UserService } from '$lib/gen' + import { Preview, UserService } from '$lib/gen' import type { Text } from 'yjs' import { initializeMode } from 'monaco-graphql/esm/initializeMode' import type { MonacoGraphQLAPI } from 'monaco-graphql/esm/api' @@ -52,6 +52,13 @@ import { editorCodeCompletion } from './copilot/completion' import { initializeVscode } from './vscode' import EditorTheme from './EditorTheme.svelte' + import { + BIGQUERY_TYPES, + MSSQL_TYPES, + MYSQL_TYPES, + POSTGRES_TYPES, + SNOWFLAKE_TYPES + } from '$lib/consts' // import EditorTheme from './EditorTheme.svelte' let divEl: HTMLDivElement | null = null @@ -66,7 +73,6 @@ | 'graphql' | 'powershell' | 'css' - export let deno: boolean export let code: string = '' export let cmdEnterAction: (() => void) | undefined = undefined export let formatAction: (() => void) | undefined = undefined @@ -90,6 +96,7 @@ export let useWebsockets: boolean = true export let listenEmptyChanges = false export let small = false + export let scriptLang: Preview.language const rHash = randomHash() $: filePath = computePath(path) @@ -119,7 +126,7 @@ let destroyed = false const uri = - lang == 'typescript' && deno + lang == 'typescript' && scriptLang === 'deno' ? `file:///${filePath ?? rHash}.${langToExt(lang)}` : `file:///tmp/monaco/${randomHash()}.${langToExt(lang)}` @@ -239,6 +246,63 @@ let command: Disposable | undefined = undefined + let sqlTypeCompletor: Disposable | undefined = undefined + + $: lang === 'sql' && scriptLang ? addSqlTypeCompletor() : sqlTypeCompletor?.dispose() + + function addSqlTypeCompletor() { + if (sqlTypeCompletor) { + sqlTypeCompletor.dispose() + } + sqlTypeCompletor = languages.registerCompletionItemProvider('sql', { + triggerCharacters: scriptLang === 'postgresql' ? [':'] : ['('], + provideCompletionItems: function (model, position) { + const lineUntilPosition = model.getValueInRange({ + startLineNumber: position.lineNumber, + startColumn: 1, + endLineNumber: position.lineNumber, + endColumn: position.column + }) + let suggestions: languages.CompletionItem[] = [] + if ( + scriptLang === 'postgresql' + ? lineUntilPosition.endsWith('::') + : lineUntilPosition.match(/^-- .* \(/) + ) { + const word = model.getWordUntilPosition(position) + const range = { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: word.startColumn, + endColumn: word.endColumn + } + suggestions = ( + scriptLang === 'postgresql' + ? POSTGRES_TYPES + : scriptLang === 'mysql' + ? MYSQL_TYPES + : scriptLang === 'snowflake' + ? SNOWFLAKE_TYPES + : scriptLang === 'bigquery' + ? BIGQUERY_TYPES + : scriptLang === 'mssql' + ? MSSQL_TYPES + : [] + ).map((t) => ({ + label: t, + kind: languages.CompletionItemKind.Function, + insertText: t, + range: range, + sortText: 'a' + })) + } + return { + suggestions + } + } + }) + } + let sqlSchemaCompletor: Disposable | undefined = undefined function updateSchema() { @@ -616,7 +680,7 @@ let encodedImportMap = '' if (useWebsockets) { - if (lang == 'typescript' && deno) { + if (lang == 'typescript' && scriptLang === 'deno') { let expiration = new Date() expiration.setHours(expiration.getHours() + 2) const token = await UserService.createToken({ @@ -682,7 +746,7 @@ ] } ) - } else if (lang === 'typescript' && !deno) { + } else if (lang === 'typescript' && scriptLang !== 'deno') { await connectToLanguageServer( `${wsProtocol}://${window.location.host}/ws/bun`, 'bun', @@ -1012,6 +1076,7 @@ websocketInterval && clearInterval(websocketInterval) sqlSchemaCompletor && sqlSchemaCompletor.dispose() copilotCompletor && copilotCompletor.dispose() + sqlTypeCompletor && sqlTypeCompletor.dispose() }) diff --git a/frontend/src/lib/components/ScriptEditor.svelte b/frontend/src/lib/components/ScriptEditor.svelte index e0d8a138ba..de1192e31b 100644 --- a/frontend/src/lib/components/ScriptEditor.svelte +++ b/frontend/src/lib/components/ScriptEditor.svelte @@ -307,7 +307,7 @@ }} class="flex flex-1 h-full !overflow-visible" lang={scriptLangToEditorLang(lang)} - deno={lang == 'deno'} + scriptLang={lang} automaticLayout={true} {fixedOverflowWidgets} {args} diff --git a/frontend/src/lib/components/WorkspaceGroup.svelte b/frontend/src/lib/components/WorkspaceGroup.svelte index daf24f8d9f..03df4dfa02 100644 --- a/frontend/src/lib/components/WorkspaceGroup.svelte +++ b/frontend/src/lib/components/WorkspaceGroup.svelte @@ -4,7 +4,7 @@ import Multiselect from 'svelte-multiselect' import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte' import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte' - import { ConfigService } from '$lib/gen' + import { ConfigService, Preview } from '$lib/gen' import ConfirmationModal from './common/confirmationModal/ConfirmationModal.svelte' import { createEventDispatcher } from 'svelte' import { sendUserToast } from '$lib/toast' @@ -353,7 +353,7 @@ class="flex flex-1 grow h-full w-full" automaticLayout lang="shell" - deno={false} + scriptLang={Preview.language.BASH} useWebsockets={false} fixedOverflowWidgets={false} listenEmptyChanges diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/CssProperty.svelte b/frontend/src/lib/components/apps/editor/componentsPanel/CssProperty.svelte index 6cddad39c1..6c6abdcb78 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/CssProperty.svelte +++ b/frontend/src/lib/components/apps/editor/componentsPanel/CssProperty.svelte @@ -202,8 +202,6 @@ fixedOverflowWidgets={true} small automaticLayout - deno={false} - subType="tailwind" /> {#if componentType && ccomponents?.[componentType]?.quickstyle?.[name]?.quickTailwindClasses} diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/CssSettings.svelte b/frontend/src/lib/components/apps/editor/componentsPanel/CssSettings.svelte index 2112cd023e..069c9fc1db 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/CssSettings.svelte +++ b/frontend/src/lib/components/apps/editor/componentsPanel/CssSettings.svelte @@ -80,7 +80,6 @@ small automaticLayout bind:this={cssEditor} - deno={false} /> {:else} diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/ThemeCodePreview.svelte b/frontend/src/lib/components/apps/editor/componentsPanel/ThemeCodePreview.svelte index a2796b1004..1245ef1cbc 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/ThemeCodePreview.svelte +++ b/frontend/src/lib/components/apps/editor/componentsPanel/ThemeCodePreview.svelte @@ -29,6 +29,5 @@ small automaticLayout bind:this={cssEditor} - deno={false} /> diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte index 52f6a13b24..4086b9d6b9 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte @@ -254,12 +254,12 @@ {#if !drawerIsOpen} {#if inlineScript.language != 'frontend'} { diff --git a/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte b/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte index 1ef175a8cf..f7edd45d24 100644 --- a/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte +++ b/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte @@ -8,7 +8,7 @@ import Toggle from '$lib/components/Toggle.svelte' import { createScriptFromInlineScript, fork } from '$lib/components/flows/flowStateUtils' - import { RawScript, type FlowModule, Script } from '$lib/gen' + import { type FlowModule, Script } from '$lib/gen' import FlowCard from '../common/FlowCard.svelte' import FlowModuleHeader from './FlowModuleHeader.svelte' import { getLatestHashForScript, scriptLangToEditorLang } from '$lib/scripts' @@ -259,8 +259,8 @@ bind:this={editor} class="h-full relative" bind:code={flowModule.value.content} - deno={flowModule.value.language === RawScript.language.DENO} lang={scriptLangToEditorLang(flowModule.value.language)} + scriptLang={flowModule.value.language} automaticLayout={true} cmdEnterAction={async () => { selected = 'test' diff --git a/frontend/src/lib/consts.ts b/frontend/src/lib/consts.ts index f76678637e..0152a71826 100644 --- a/frontend/src/lib/consts.ts +++ b/frontend/src/lib/consts.ts @@ -43,3 +43,135 @@ export const WORKER_S3_BUCKET_SYNC_SETTING = 'worker_s3_bucket_sync' export const CUSTOM_TAGS_SETTING = 'custom_tags' export const WORKSPACE_SLACK_BOT_TOKEN_PATH = 'f/slack_bot/bot_token' + +export const POSTGRES_TYPES = [ + 'VARCHAR', + 'VARCHAR[]', + 'TEXT', + 'TEXT[]', + 'INT', + 'INT[]', + 'BIGINT', + 'BIGINT[]', + 'BOOL', + 'BOOL[]', + 'CHAR', + 'CHAR[]', + 'SMALLINT', + 'SMALLINT[]', + 'SMALLSERIAL', + 'SMALLSERIAL[]', + 'SERIAL', + 'SERIAL[]', + 'BIGSERIAL', + 'BIGSERIAL[]', + 'REAL', + 'REAL[]', + 'DOUBLE PRECISION', + 'DOUBLE PRECISION[]', + 'NUMERIC', + 'NUMERIC[]', + 'DECIMAL', + 'DECIMAL[]', + 'OID', + 'OID[]', + 'DATE', + 'DATE[]', + 'TIME', + 'TIME[]', + 'TIMESTAMP', + 'TIMESTAMP[]' +] + +export const MYSQL_TYPES = [ + 'varchar', + 'char', + 'bin', + 'varbinary', + 'blob', + 'text', + 'enum', + 'set', + 'int', + 'uint', + 'integer', + 'bool', + 'bit', + 'float', + 'real', + 'dec', + 'fixed', + 'date', + 'datetime', + 'timestamp', + 'time' +] + +export const BIGQUERY_TYPES = [ + 'string', + 'string[]', + 'bytes', + 'bytes[]', + 'json', + 'json[]', + 'timestamp', + 'timestamp[]', + 'date', + 'date[]', + 'time', + 'time[]', + 'datetime', + 'datetime[]', + 'integer', + 'integer[]', + 'int64', + 'int64[]', + 'float', + 'float[]', + 'float64', + 'float64[]', + 'numeric', + 'numeric[]', + 'bignumeric', + 'bignumeric[]', + 'bool', + 'bool[]' +] + +export const SNOWFLAKE_TYPES = [ + 'varchar', + 'binary', + 'date', + 'time', + 'timestamp', + 'int', + 'float', + 'boolean' +] + +export const MSSQL_TYPES = [ + 'char', + 'varchar', + 'text', + 'nchar', + 'nvarchar', + 'ntext', + 'binary', + 'varbinary', + 'image', + 'date', + 'datetime2', + 'datetime', + 'datetimeoffset', + 'smalldatetime', + 'time', + 'bigint', + 'int', + 'tinyint', + 'smallint', + 'float', + 'real', + 'numeric', + 'decimal', + 'bit' +]