diff options
author | 2022-07-24 14:37:27 +0200 | |
---|---|---|
committer | 2022-07-24 14:37:27 +0200 | |
commit | d1f95f5b34a4570f1033a5289f0bd009d1aefb0c (patch) | |
tree | a89a02a805676b0ff359a90e922881ca2c4b3e92 | |
parent | 6cd25a743e32fceeaec8c1f8b94927a9c5d901f1 (diff) | |
download | it-tools-d1f95f5b34a4570f1033a5289f0bd009d1aefb0c.tar.gz it-tools-d1f95f5b34a4570f1033a5289f0bd009d1aefb0c.tar.zst it-tools-d1f95f5b34a4570f1033a5289f0bd009d1aefb0c.zip |
feat(new-tool): added an SQL prettifier and formatter
-rw-r--r-- | package-lock.json | 26 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/tools/index.ts | 3 | ||||
-rw-r--r-- | src/tools/sql-prettify/index.ts | 26 | ||||
-rw-r--r-- | src/tools/sql-prettify/sql-prettify.service.test.ts | 6 | ||||
-rw-r--r-- | src/tools/sql-prettify/sql-prettify.service.ts | 0 | ||||
-rw-r--r-- | src/tools/sql-prettify/sql-prettify.vue | 112 |
7 files changed, 169 insertions, 5 deletions
diff --git a/package-lock.json b/package-lock.json index bb48154..6779bae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "plausible-tracker": "^0.3.5", "qrcode": "^1.5.0", "randombytes": "^2.1.0", + "sql-formatter": "^8.2.0", "uuid": "^8.3.2", "vue": "^3.2.31", "vue-router": "^4.0.12" @@ -3089,8 +3090,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-ify": { "version": "1.0.0", @@ -9580,6 +9580,17 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/sql-formatter": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-8.2.0.tgz", + "integrity": "sha512-5hQOSOk8jfhPkNgUmpm+9Fn2aaLWcf4vKL/dIvUN5q9rsamKHSyN/gL79xpkETNOyL+Zv5BMQfA7z9Rmz/DJJg==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "sql-formatter": "bin/sql-formatter-cli.js" + } + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -13660,8 +13671,7 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "array-ify": { "version": "1.0.0", @@ -18502,6 +18512,14 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sql-formatter": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-8.2.0.tgz", + "integrity": "sha512-5hQOSOk8jfhPkNgUmpm+9Fn2aaLWcf4vKL/dIvUN5q9rsamKHSyN/gL79xpkETNOyL+Zv5BMQfA7z9Rmz/DJJg==", + "requires": { + "argparse": "^2.0.1" + } + }, "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", diff --git a/package.json b/package.json index 465b81b..dbbf610 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "plausible-tracker": "^0.3.5", "qrcode": "^1.5.0", "randombytes": "^2.1.0", + "sql-formatter": "^8.2.0", "uuid": "^8.3.2", "vue": "^3.2.31", "vue-router": "^4.0.12" diff --git a/src/tools/index.ts b/src/tools/index.ts index eeed10c..22613d3 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -21,6 +21,7 @@ import { tool as mathEvaluator } from './math-evaluator'; import { tool as qrCodeGenerator } from './qr-code-generator'; import { tool as randomPortGenerator } from './random-port-generator'; import { tool as romanNumeralConverter } from './roman-numeral-converter'; +import { tool as sqlPrettify } from './sql-prettify'; import { tool as textStatistics } from './text-statistics'; import { tool as tokenGenerator } from './token-generator'; import { tool as urlEncoder } from './url-encoder'; @@ -53,7 +54,7 @@ export const toolsByCategory: ToolCategory[] = [ { name: 'Development', icon: LockOpen, - components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer], + components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer, sqlPrettify], }, { name: 'Math', diff --git a/src/tools/sql-prettify/index.ts b/src/tools/sql-prettify/index.ts new file mode 100644 index 0000000..426845f --- /dev/null +++ b/src/tools/sql-prettify/index.ts @@ -0,0 +1,26 @@ +import { Database } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'SQL prettify and format', + path: '/sql-prettify', + description: 'Format and prettify your SQL queries online (it supports various SQL dialects).', + keywords: [ + 'sql', + 'prettify', + 'beautify', + 'GCP BigQuery', + 'IBM DB2', + 'Apache Hive', + 'MariaDB', + 'MySQL', + 'Couchbase N1QL', + 'Oracle PL/SQL', + 'PostgreSQL', + 'Amazon Redshift', + 'Spark', + 'SQL Server Transact-SQL', + ], + component: () => import('./sql-prettify.vue'), + icon: Database, +}); diff --git a/src/tools/sql-prettify/sql-prettify.service.test.ts b/src/tools/sql-prettify/sql-prettify.service.test.ts new file mode 100644 index 0000000..aadcd84 --- /dev/null +++ b/src/tools/sql-prettify/sql-prettify.service.test.ts @@ -0,0 +1,6 @@ +import { expect, describe, it } from 'vitest'; +// import { } from './sql-prettify.service'; +// +// describe('sql-prettify', () => { +// +// })
\ No newline at end of file diff --git a/src/tools/sql-prettify/sql-prettify.service.ts b/src/tools/sql-prettify/sql-prettify.service.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/tools/sql-prettify/sql-prettify.service.ts diff --git a/src/tools/sql-prettify/sql-prettify.vue b/src/tools/sql-prettify/sql-prettify.vue new file mode 100644 index 0000000..8e05158 --- /dev/null +++ b/src/tools/sql-prettify/sql-prettify.vue @@ -0,0 +1,112 @@ +<template> + <div style="flex: 0 0 100%"> + <div style="margin: 0 auto; width: 600px"> + <n-space n-space item-style="flex: 1 1 0"> + <div> + <n-form-item label="Dialect"> + <n-select + v-model:value="config.language" + :options="[ + { label: 'GCP BigQuery', value: 'bigquery' }, + { label: 'IBM DB2', value: 'db2' }, + { label: 'Apache Hive', value: 'hive' }, + { label: 'MariaDB', value: 'mariadb' }, + { label: 'MySQL', value: 'mysql' }, + { label: 'Couchbase N1QL', value: 'n1ql' }, + { label: 'Oracle PL/SQL', value: 'plsql' }, + { label: 'PostgreSQL', value: 'postgresql' }, + { label: 'Amazon Redshift', value: 'redshift' }, + { label: 'Spark', value: 'spark' }, + { label: 'Standard SQL', value: 'sql' }, + { label: 'sqlite', value: 'sqlite' }, + { label: 'SQL Server Transact-SQL', value: 'tsql' }, + ]" + /> + </n-form-item> + </div> + <div> + <n-form-item label="Keyword case"> + <n-select + v-model:value="config.keywordCase" + :options="[ + { label: 'UPPERCASE', value: 'upper' }, + { label: 'lowercase', value: 'lower' }, + { label: 'Preserve', value: 'preserve' }, + ]" + /> + </n-form-item> + </div> + <div> + <n-form-item label="Indent style"> + <n-select + v-model:value="config.indentStyle" + :options="[ + { label: 'Standard', value: 'standard' }, + { label: 'Tabular left', value: 'tabularLeft' }, + { label: 'Tabular right', value: 'tabularRight' }, + ]" + /> + </n-form-item> + </div> + </n-space> + </div> + </div> + + <n-form-item label="Your SQL query"> + <n-input + ref="inputElement" + v-model:value="rawSQL" + placeholder="Put your SQL query here..." + type="textarea" + rows="20" + autocomplete="off" + autocorrect="off" + autocapitalize="off" + spellcheck="false" + /> + </n-form-item> + <n-form-item label="Prettify version of your query"> + <n-card class="result-card" :style="`min-height: ${inputElementHeight ?? 400}px`"> + <n-config-provider :hljs="hljs"> + <n-code :code="prettySQL" language="sql" :trim="false" /> + </n-config-provider> + <n-button v-if="prettySQL" class="copy-button" secondary @click="copy">Copy</n-button> + </n-card> + </n-form-item> +</template> + +<script setup lang="ts"> +import { useCopy } from '@/composable/copy'; +import { useElementSize } from '@vueuse/core'; +import hljs from 'highlight.js/lib/core'; +import sqlHljs from 'highlight.js/lib/languages/sql'; +import { format as formatSQL, type FormatFnOptions } from 'sql-formatter'; +import { computed, reactive, ref } from 'vue'; +hljs.registerLanguage('sql', sqlHljs); + +const inputElement = ref<HTMLElement>(); +const { height: inputElementHeight } = useElementSize(inputElement); + +const config = reactive<Partial<FormatFnOptions>>({ + keywordCase: 'upper', + useTabs: false, + language: 'sql', + indentStyle: 'standard', + tabulateAlias: true, +}); + +const rawSQL = ref('select field1,field2,field3 from my_table where my_condition;'); +const prettySQL = computed(() => formatSQL(rawSQL.value, config)); +const { copy } = useCopy({ source: prettySQL }); +</script> + +<style lang="less" scoped> +.result-card { + position: relative; + .copy-button { + position: absolute; + top: 10px; + right: 10px; + } +} +</style> |