feat(editor): SQL editor overhaul (#6282)

* Draft setup
*  Implemented expression evaluation in Postgres node, minor SQL editor UI improvements, minor refacring
*  Added initial version of expression preview for SQL editor
*  Linking npm package for codemirror sql grammar instead of a local file
*  Moving expression editor wrapper elements to the component
*  Using expression preview in SQL editor
* Use SQL parser skipping whitespace
*  Added support for custom skipped segments specification
*  Fixing highlight problems with dots and expressions that resolve to zero
* 👕 Fixing linting error
*  Added current item support
*  Added expression support to more nodes with sql editor
*  Added expression support for other nodes
*  Implemented different SQL dialect support
* 🐛 Fixing hard-coded parameter names for editors
*  Fixing preview for nested queries, updating query when input data changes, adding keyboard shortcut to toggle comments
*  Adding a custom automcomplete notice for different editors
*  Updating SQL autocomplete notice
*  Added unit tests for SQL editor
*  Using latest grammar
* 🐛 Fixing code node editor rendering
* 💄 SQL preview dropdown matches editor width. Removing unnecessary css
*  Addressing PR review feedback
* 👌 Addressing PR review feedback pt2
* 👌 Added path alias for utils in nodes-base package
* 👌 Addressing more PR review feedback
*  Adding tests for `getResolvables` utility function
* Fixing lodash imports
* 👌 Better focus handling, adding more plugins to the editor, other minor imrovements
*  Not showing SQL autocomplete suggestions inside expressions
*  Using npm package for sql grammar
*  Removing autocomplete notice, adding line highlight on syntax error
* 👌 Addressing code review feedback
---------
Co-authored-by: Milorad Filipovic <milorad@n8n.io>
This commit is contained in:
Iván Ovejero
2023-06-22 16:47:28 +02:00
committed by GitHub
parent d431117c9e
commit beedfb609c
68 changed files with 653 additions and 287 deletions

View File

@@ -17,7 +17,7 @@ import type mysql2 from 'mysql2/promise';
import { copyInputItems, createConnection, searchTables } from './GenericFunctions';
import type { IExecuteFunctions } from 'n8n-core';
import { oldVersionNotice } from '../../../utils/descriptions';
import { oldVersionNotice } from '@utils/descriptions';
const versionDescription: INodeTypeDescription = {
displayName: 'MySQL',
@@ -75,9 +75,10 @@ const versionDescription: INodeTypeDescription = {
displayName: 'Query',
name: 'query',
type: 'string',
noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
sqlDialect: 'mysql',
sqlDialect: 'MySQL',
},
displayOptions: {
show: {

View File

@@ -9,7 +9,7 @@ import type {
WhereClause,
} from '../../helpers/interfaces';
import { updateDisplayOptions } from '../../../../../utils/utilities';
import { updateDisplayOptions } from '@utils/utilities';
import { addWhereClauses } from '../../helpers/utils';

View File

@@ -4,7 +4,7 @@ import { NodeOperationError } from 'n8n-workflow';
import type { QueryRunner, QueryWithValues } from '../../helpers/interfaces';
import { updateDisplayOptions } from '../../../../../utils/utilities';
import { getResolvables, updateDisplayOptions } from '@utils/utilities';
import { prepareQueryAndReplacements, replaceEmptyStringsByNulls } from '../../helpers/utils';
@@ -20,9 +20,10 @@ const properties: INodeProperties[] = [
required: true,
description:
"The SQL query to execute. You can use n8n expressions and $1, $2, $3, etc to refer to the 'Query Parameters' set in options below.",
noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
sqlDialect: 'mysql',
sqlDialect: 'MySQL',
},
hint: 'Prefer using query parameters over n8n expressions to avoid SQL injection attacks',
},
@@ -58,7 +59,11 @@ export async function execute(
const queries: QueryWithValues[] = [];
for (let i = 0; i < items.length; i++) {
const rawQuery = this.getNodeParameter('query', i) as string;
let rawQuery = this.getNodeParameter('query', i) as string;
for (const resolvable of getResolvables(rawQuery)) {
rawQuery = rawQuery.replace(resolvable, this.evaluateExpression(resolvable, i) as string);
}
const options = this.getNodeParameter('options', i, {});

View File

@@ -10,7 +10,7 @@ import type {
import { AUTO_MAP, BATCH_MODE, DATA_MODE } from '../../helpers/interfaces';
import { updateDisplayOptions } from '../../../../../utils/utilities';
import { updateDisplayOptions } from '@utils/utilities';
import { copyInputItems, replaceEmptyStringsByNulls } from '../../helpers/utils';

View File

@@ -9,7 +9,7 @@ import type {
WhereClause,
} from '../../helpers/interfaces';
import { updateDisplayOptions } from '../../../../../utils/utilities';
import { updateDisplayOptions } from '@utils/utilities';
import { addSortRules, addWhereClauses } from '../../helpers/utils';

View File

@@ -4,7 +4,7 @@ import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workf
import type { QueryRunner, QueryValues, QueryWithValues } from '../../helpers/interfaces';
import { AUTO_MAP, DATA_MODE } from '../../helpers/interfaces';
import { updateDisplayOptions } from '../../../../../utils/utilities';
import { updateDisplayOptions } from '@utils/utilities';
import { replaceEmptyStringsByNulls } from '../../helpers/utils';

View File

@@ -4,7 +4,7 @@ import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workf
import type { QueryRunner, QueryValues, QueryWithValues } from '../../helpers/interfaces';
import { AUTO_MAP, DATA_MODE } from '../../helpers/interfaces';
import { updateDisplayOptions } from '../../../../../utils/utilities';
import { updateDisplayOptions } from '@utils/utilities';
import { replaceEmptyStringsByNulls } from '../../helpers/utils';