feat(new-tool): added an SQL prettifier and formatter
This commit is contained in:
		
							parent
							
								
									6cd25a743e
								
							
						
					
					
						commit
						d1f95f5b34
					
				
							
								
								
									
										26
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										26
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -30,6 +30,7 @@ | |||||||
|         "plausible-tracker": "^0.3.5", |         "plausible-tracker": "^0.3.5", | ||||||
|         "qrcode": "^1.5.0", |         "qrcode": "^1.5.0", | ||||||
|         "randombytes": "^2.1.0", |         "randombytes": "^2.1.0", | ||||||
|  |         "sql-formatter": "^8.2.0", | ||||||
|         "uuid": "^8.3.2", |         "uuid": "^8.3.2", | ||||||
|         "vue": "^3.2.31", |         "vue": "^3.2.31", | ||||||
|         "vue-router": "^4.0.12" |         "vue-router": "^4.0.12" | ||||||
| @ -3089,8 +3090,7 @@ | |||||||
|     "node_modules/argparse": { |     "node_modules/argparse": { | ||||||
|       "version": "2.0.1", |       "version": "2.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", |       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", | ||||||
|       "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", |       "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/array-ify": { |     "node_modules/array-ify": { | ||||||
|       "version": "1.0.0", |       "version": "1.0.0", | ||||||
| @ -9580,6 +9580,17 @@ | |||||||
|       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", |       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", | ||||||
|       "dev": true |       "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": { |     "node_modules/stable": { | ||||||
|       "version": "0.1.8", |       "version": "0.1.8", | ||||||
|       "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", |       "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", | ||||||
| @ -13660,8 +13671,7 @@ | |||||||
|     "argparse": { |     "argparse": { | ||||||
|       "version": "2.0.1", |       "version": "2.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", |       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", | ||||||
|       "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", |       "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "array-ify": { |     "array-ify": { | ||||||
|       "version": "1.0.0", |       "version": "1.0.0", | ||||||
| @ -18502,6 +18512,14 @@ | |||||||
|       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", |       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", | ||||||
|       "dev": true |       "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": { |     "stable": { | ||||||
|       "version": "0.1.8", |       "version": "0.1.8", | ||||||
|       "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", |       "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ | |||||||
|     "plausible-tracker": "^0.3.5", |     "plausible-tracker": "^0.3.5", | ||||||
|     "qrcode": "^1.5.0", |     "qrcode": "^1.5.0", | ||||||
|     "randombytes": "^2.1.0", |     "randombytes": "^2.1.0", | ||||||
|  |     "sql-formatter": "^8.2.0", | ||||||
|     "uuid": "^8.3.2", |     "uuid": "^8.3.2", | ||||||
|     "vue": "^3.2.31", |     "vue": "^3.2.31", | ||||||
|     "vue-router": "^4.0.12" |     "vue-router": "^4.0.12" | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ import { tool as mathEvaluator } from './math-evaluator'; | |||||||
| import { tool as qrCodeGenerator } from './qr-code-generator'; | import { tool as qrCodeGenerator } from './qr-code-generator'; | ||||||
| import { tool as randomPortGenerator } from './random-port-generator'; | import { tool as randomPortGenerator } from './random-port-generator'; | ||||||
| import { tool as romanNumeralConverter } from './roman-numeral-converter'; | 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 textStatistics } from './text-statistics'; | ||||||
| import { tool as tokenGenerator } from './token-generator'; | import { tool as tokenGenerator } from './token-generator'; | ||||||
| import { tool as urlEncoder } from './url-encoder'; | import { tool as urlEncoder } from './url-encoder'; | ||||||
| @ -53,7 +54,7 @@ export const toolsByCategory: ToolCategory[] = [ | |||||||
|   { |   { | ||||||
|     name: 'Development', |     name: 'Development', | ||||||
|     icon: LockOpen, |     icon: LockOpen, | ||||||
|     components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer], |     components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer, sqlPrettify], | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: 'Math', |     name: 'Math', | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								src/tools/sql-prettify/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/tools/sql-prettify/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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, | ||||||
|  | }); | ||||||
							
								
								
									
										6
									
								
								src/tools/sql-prettify/sql-prettify.service.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/tools/sql-prettify/sql-prettify.service.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | import { expect, describe, it } from 'vitest'; | ||||||
|  | // import { } from './sql-prettify.service';
 | ||||||
|  | //
 | ||||||
|  | // describe('sql-prettify', () => {
 | ||||||
|  | //
 | ||||||
|  | // })
 | ||||||
							
								
								
									
										0
									
								
								src/tools/sql-prettify/sql-prettify.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/tools/sql-prettify/sql-prettify.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										112
									
								
								src/tools/sql-prettify/sql-prettify.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/tools/sql-prettify/sql-prettify.vue
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user