aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json26
-rw-r--r--package.json1
-rw-r--r--src/tools/index.ts3
-rw-r--r--src/tools/sql-prettify/index.ts26
-rw-r--r--src/tools/sql-prettify/sql-prettify.service.test.ts6
-rw-r--r--src/tools/sql-prettify/sql-prettify.service.ts0
-rw-r--r--src/tools/sql-prettify/sql-prettify.vue112
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>