diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json
index 0f9d8a9c25ff6..1312df7888ab1 100644
--- a/packages/editor-ui/package.json
+++ b/packages/editor-ui/package.json
@@ -31,7 +31,6 @@
"@codemirror/lang-javascript": "^6.1.2",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-python": "^6.1.2",
- "@codemirror/lang-sql": "^6.4.1",
"@codemirror/language": "^6.2.1",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.1.4",
@@ -46,6 +45,7 @@
"@jsplumb/connector-bezier": "^5.13.2",
"@jsplumb/core": "^5.13.2",
"@jsplumb/util": "^5.13.2",
+ "@n8n/codemirror-lang-sql": "^1.0.0",
"axios": "^0.21.1",
"codemirror-lang-html-n8n": "^1.0.0",
"codemirror-lang-n8n-expression": "^0.2.0",
diff --git a/packages/editor-ui/src/components/CodeNodeEditor/theme.ts b/packages/editor-ui/src/components/CodeNodeEditor/theme.ts
index 166d214be89ac..f54afaf71f2f1 100644
--- a/packages/editor-ui/src/components/CodeNodeEditor/theme.ts
+++ b/packages/editor-ui/src/components/CodeNodeEditor/theme.ts
@@ -31,9 +31,10 @@ const cssStyleDeclaration = getComputedStyle(document.documentElement);
interface ThemeSettings {
isReadOnly?: boolean;
+ customMaxHeight?: string;
}
-export const codeNodeEditorTheme = ({ isReadOnly }: ThemeSettings) => [
+export const codeNodeEditorTheme = ({ isReadOnly, customMaxHeight }: ThemeSettings) => [
EditorView.theme({
'&': {
'font-size': BASE_STYLING.fontSize,
@@ -79,7 +80,7 @@ export const codeNodeEditorTheme = ({ isReadOnly }: ThemeSettings) => [
},
'.cm-scroller': {
overflow: 'auto',
- maxHeight: '100%',
+ maxHeight: customMaxHeight ?? '100%',
...(isReadOnly ? {} : { minHeight: '10em' }),
},
'.cm-diagnosticAction': {
diff --git a/packages/editor-ui/src/components/ExpressionParameterInput.vue b/packages/editor-ui/src/components/ExpressionParameterInput.vue
index c1e56ed90c32b..c597a1edd5c1c 100644
--- a/packages/editor-ui/src/components/ExpressionParameterInput.vue
+++ b/packages/editor-ui/src/components/ExpressionParameterInput.vue
@@ -31,36 +31,13 @@
/>
-
-
- {{ $locale.baseText('parameterInput.resultForItem') }} {{ hoveringItemNumber }}
-
-
-
-
-
-
- {{ $locale.baseText('parameterInput.anythingInside') }}
-
-
-
- {{ $locale.baseText('parameterInput.isJavaScript') }}
-
-
- {{ $locale.baseText('parameterInput.learnMore') }}
-
-
-
+
@@ -74,7 +51,6 @@ import InlineExpressionEditorInput from '@/components/InlineExpressionEditor/Inl
import InlineExpressionEditorOutput from '@/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue';
import ExpressionFunctionIcon from '@/components/ExpressionFunctionIcon.vue';
import { createExpressionTelemetryPayload } from '@/utils/telemetryUtils';
-import { EXPRESSIONS_DOCS_URL } from '@/constants';
import type { Segment } from '@/types/expressions';
import type { TargetItem } from '@/Interface';
@@ -92,7 +68,6 @@ export default defineComponent({
return {
isFocused: false,
segments: [] as Segment[],
- expressionsDocsUrl: EXPRESSIONS_DOCS_URL,
};
},
props: {
@@ -114,14 +89,10 @@ export default defineComponent({
computed: {
...mapStores(useNDVStore, useWorkflowsStore),
hoveringItemNumber(): number {
- return (this.hoveringItem?.itemIndex ?? 0) + 1;
+ return this.ndvStore.hoveringItemNumber;
},
hoveringItem(): TargetItem | null {
- if (this.ndvStore.isInputParentOfActiveNode) {
- return this.ndvStore.hoveringItem;
- }
-
- return null;
+ return this.ndvStore.getHoveringItem;
},
isDragging(): boolean {
return this.ndvStore.isDraggableDragging;
@@ -241,64 +212,4 @@ export default defineComponent({
border-bottom-right-radius: 0;
background-color: white;
}
-
-.hidden {
- display: none;
-}
-
-.dropdown {
- display: flex;
- flex-direction: column;
- position: absolute;
- z-index: 2; // cover tooltips
- background: white;
- border: var(--border-base);
- border-top: none;
- width: 100%;
- box-shadow: 0 2px 6px 0 rgba(#441c17, 0.1);
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
-
- .header,
- .body,
- .footer {
- padding: var(--spacing-3xs);
- }
-
- .header {
- color: var(--color-text-dark);
- font-weight: var(--font-weight-bold);
- padding-left: var(--spacing-2xs);
- padding-top: var(--spacing-2xs);
- }
-
- .body {
- padding-top: 0;
- padding-left: var(--spacing-2xs);
- color: var(--color-text-dark);
- }
-
- .footer {
- border-top: var(--border-base);
- padding: var(--spacing-4xs);
- padding-left: var(--spacing-2xs);
- padding-top: 0;
- line-height: var(--font-line-height-regular);
- color: var(--color-text-base);
-
- .expression-syntax-example {
- display: inline-block;
- font-size: var(--font-size-2xs);
- height: var(--font-size-m);
- background-color: #f0f0f0;
- margin-left: var(--spacing-5xs);
- margin-right: var(--spacing-5xs);
- }
-
- .learn-more {
- line-height: 1;
- white-space: nowrap;
- }
- }
-}
diff --git a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue
index b64a70a2df3ab..472fef3ed2e03 100644
--- a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue
+++ b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue
@@ -1,5 +1,30 @@
-
+
+
+ {{ $locale.baseText('parameterInput.resultForItem') }} {{ hoveringItemNumber }}
+
+
+
+
+
+
+ {{ $locale.baseText('parameterInput.anythingInside') }}
+
+
+
+ {{ $locale.baseText('parameterInput.isJavaScript') }}
+
+
+ {{ $locale.baseText('parameterInput.learnMore') }}
+
+
+
-
+
diff --git a/packages/editor-ui/src/components/ParameterOptions.vue b/packages/editor-ui/src/components/ParameterOptions.vue
index e4453ccc72490..a00bb5c22da48 100644
--- a/packages/editor-ui/src/components/ParameterOptions.vue
+++ b/packages/editor-ui/src/components/ParameterOptions.vue
@@ -107,7 +107,7 @@ export default defineComponent({
return false;
}
- if (this.parameter.typeOptions?.editor === 'codeNodeEditor') {
+ if (['codeNodeEditor', 'sqlEditor'].includes(this.parameter.typeOptions?.editor)) {
return false;
}
diff --git a/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue b/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue
index adac053295961..09cee368d0bec 100644
--- a/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue
+++ b/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue
@@ -1,17 +1,23 @@
-
+
+
+
diff --git a/packages/editor-ui/src/components/__tests__/SQLEditor.test.ts b/packages/editor-ui/src/components/__tests__/SQLEditor.test.ts
new file mode 100644
index 0000000000000..af33117c63e16
--- /dev/null
+++ b/packages/editor-ui/src/components/__tests__/SQLEditor.test.ts
@@ -0,0 +1,112 @@
+import { render } from '@testing-library/vue';
+import { PiniaVuePlugin } from 'pinia';
+import { SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
+import { STORES } from '@/constants';
+import { createTestingPinia } from '@pinia/testing';
+
+import SqlEditor from '@/components/SqlEditor/SqlEditor.vue';
+import { expressionManager } from '@/mixins/expressionManager';
+import type { TargetItem } from '@/Interface';
+
+const EXPRESSION_OUTPUT_TEST_ID = 'inline-expression-editor-output';
+
+const RESOLVABLES: { [key: string]: string | number | boolean } = {
+ '{{ $json.schema }}': 'public',
+ '{{ $json.table }}': 'users',
+ '{{ $json.id }}': 'id',
+ '{{ $json.limit - 10 }}': 0,
+ '{{ $json.active }}': false,
+};
+
+const DEFAULT_SETUP = {
+ pinia: createTestingPinia({
+ initialState: {
+ [STORES.SETTINGS]: {
+ settings: SETTINGS_STORE_DEFAULT_STATE.settings,
+ },
+ },
+ }),
+ props: {
+ dialect: 'PostgreSQL',
+ isReadOnly: false,
+ },
+};
+
+const renderComponent = (renderOptions: Parameters[1] = {}) =>
+ render(SqlEditor, { ...DEFAULT_SETUP, ...renderOptions }, (vue) => {
+ vue.use(PiniaVuePlugin);
+ });
+
+describe('SQL Editor Preview Tests', () => {
+ beforeEach(() => {
+ vi.spyOn(expressionManager.methods, 'resolve').mockImplementation(
+ (resolvable: string, _targetItem?: TargetItem) => {
+ return { resolved: RESOLVABLES[resolvable] };
+ },
+ );
+ });
+
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('renders basic query', async () => {
+ const { getByTestId } = renderComponent({
+ props: {
+ query: 'SELECT * FROM users',
+ },
+ });
+ await waitAllPromises();
+ expect(getByTestId(EXPRESSION_OUTPUT_TEST_ID)).toHaveTextContent('SELECT * FROM users');
+ });
+
+ it('renders basic query with expression', async () => {
+ const { getByTestId } = renderComponent({
+ props: {
+ query: 'SELECT * FROM {{ $json.table }}',
+ },
+ });
+ await waitAllPromises();
+ expect(getByTestId(EXPRESSION_OUTPUT_TEST_ID)).toHaveTextContent('SELECT * FROM users');
+ });
+
+ it('renders resolved expressions with dot between resolvables', async () => {
+ const { getByTestId } = renderComponent({
+ props: {
+ query: 'SELECT * FROM {{ $json.schema }}.{{ $json.table }}',
+ },
+ });
+ await waitAllPromises();
+ expect(getByTestId(EXPRESSION_OUTPUT_TEST_ID)).toHaveTextContent('SELECT * FROM public.users');
+ });
+
+ it('renders resolved expressions which resolve to 0', async () => {
+ const { getByTestId } = renderComponent({
+ props: {
+ query:
+ 'SELECT * FROM {{ $json.schema }}.{{ $json.table }} WHERE {{ $json.id }} > {{ $json.limit - 10 }}',
+ },
+ });
+ await waitAllPromises();
+ expect(getByTestId(EXPRESSION_OUTPUT_TEST_ID)).toHaveTextContent(
+ 'SELECT * FROM public.users WHERE id > 0',
+ );
+ });
+
+ it('keeps query formatting in rendered output', async () => {
+ const { getByTestId } = renderComponent({
+ props: {
+ query:
+ 'SELECT * FROM {{ $json.schema }}.{{ $json.table }}\n WHERE id > {{ $json.limit - 10 }}\n AND active = {{ $json.active }};',
+ },
+ });
+ await waitAllPromises();
+ expect(getByTestId(EXPRESSION_OUTPUT_TEST_ID)).toHaveTextContent(
+ 'SELECT * FROM public.users WHERE id > 0 AND active = false;',
+ );
+ // Output should have the same number of lines as the input
+ expect(getByTestId('sql-editor-container').getElementsByClassName('cm-line').length).toEqual(
+ getByTestId(EXPRESSION_OUTPUT_TEST_ID).getElementsByClassName('cm-line').length,
+ );
+ });
+});
diff --git a/packages/editor-ui/src/mixins/expressionManager.ts b/packages/editor-ui/src/mixins/expressionManager.ts
index e4a8128a838b5..f0cf517e5026e 100644
--- a/packages/editor-ui/src/mixins/expressionManager.ts
+++ b/packages/editor-ui/src/mixins/expressionManager.ts
@@ -23,6 +23,7 @@ export const expressionManager = defineComponent({
data() {
return {
editor: {} as EditorView,
+ skipSegments: [] as string[],
};
},
watch: {
@@ -71,6 +72,8 @@ export const expressionManager = defineComponent({
},
segments(): Segment[] {
+ if (!this.editor?.state) return [];
+
const rawSegments: RawSegment[] = [];
const fullTree = ensureSyntaxTree(
@@ -83,14 +86,18 @@ export const expressionManager = defineComponent({
throw new Error(`Failed to parse expression: ${this.editor.state.doc.toString()}`);
}
+ const skipSegments = ['Program', 'Script', 'Document', ...this.skipSegments];
+
fullTree.cursor().iterate((node) => {
- if (node.type.name === 'Program') return;
+ const text = this.editor.state.sliceDoc(node.from, node.to);
+
+ if (skipSegments.includes(node.type.name)) return;
rawSegments.push({
from: node.from,
to: node.to,
- text: this.editor.state.sliceDoc(node.from, node.to),
- token: node.type.name,
+ text,
+ token: node.type.name === 'Resolvable' ? 'Resolvable' : 'Plaintext',
});
});
@@ -100,7 +107,18 @@ export const expressionManager = defineComponent({
if (token === 'Resolvable') {
const { resolved, error, fullError } = this.resolve(text, this.hoveringItem);
- acc.push({ kind: 'resolvable', from, to, resolvable: text, resolved, error, fullError });
+ acc.push({
+ kind: 'resolvable',
+ from,
+ to,
+ resolvable: text,
+ // TODO:
+ // For some reason, expressions that resolve to a number 0 are breaking preview in the SQL editor
+ // This fixes that but as as TODO we should figure out why this is happening
+ resolved: String(resolved),
+ error,
+ fullError,
+ });
return acc;
}
diff --git a/packages/editor-ui/src/stores/ndv.store.ts b/packages/editor-ui/src/stores/ndv.store.ts
index 3778255f41021..7b884219fd9a7 100644
--- a/packages/editor-ui/src/stores/ndv.store.ts
+++ b/packages/editor-ui/src/stores/ndv.store.ts
@@ -4,6 +4,7 @@ import type {
IRunDataDisplayMode,
NDVState,
NodePanelType,
+ TargetItem,
XYPosition,
} from '@/Interface';
import type { INodeIssues, IRunData } from 'n8n-workflow';
@@ -125,6 +126,16 @@ export const useNDVStore = defineStore(STORES.NDV, {
const parentNodes = workflow.getParentNodes(this.activeNode.name, 'main', 1);
return parentNodes.includes(inputNodeName);
},
+ hoveringItemNumber(): number {
+ return (this.hoveringItem?.itemIndex ?? 0) + 1;
+ },
+ getHoveringItem(): TargetItem | null {
+ if (this.isInputParentOfActiveNode) {
+ return this.hoveringItem;
+ }
+
+ return null;
+ },
},
actions: {
setInputNodeName(nodeName: string | undefined): void {
diff --git a/packages/editor-ui/src/styles/autocomplete-theme.scss b/packages/editor-ui/src/styles/autocomplete-theme.scss
index 5cdf4f7442ffd..5c406de1f27c1 100644
--- a/packages/editor-ui/src/styles/autocomplete-theme.scss
+++ b/packages/editor-ui/src/styles/autocomplete-theme.scss
@@ -1,10 +1,13 @@
.cm-tooltip-autocomplete:after {
- display: block;
- content: 'n8n supports all JavaScript functions, including those not listed.';
padding: var(--spacing-2xs) var(--spacing-s);
border-top: 1px solid var(--color-foreground-dark);
}
+.code-node-editor .cm-tooltip-autocomplete:after {
+ display: block;
+ content: 'n8n supports all JavaScript functions, including those not listed.';
+}
+
// Custom autocomplete item type icons
// 1. Native and n8n extension functions:
.cm-completionIcon-extension-function, .cm-completionIcon-native-function {
diff --git a/packages/nodes-base/jest.config.js b/packages/nodes-base/jest.config.js
index 5fcf33c3358dc..d21cd780b87ee 100644
--- a/packages/nodes-base/jest.config.js
+++ b/packages/nodes-base/jest.config.js
@@ -4,5 +4,6 @@ module.exports = {
collectCoverageFrom: ['credentials/**/*.ts', 'nodes/**/*.ts', 'utils/**/*.ts'],
moduleNameMapper: {
'^@test/(.*)$': '/test/$1',
+ '^@utils/(.*)$': '/utils/$1',
},
};
diff --git a/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts b/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts
index d3c66edba81ce..c8e4709c464c8 100644
--- a/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/CompareDatasets/GenericFunctions.ts
@@ -9,7 +9,7 @@ import unset from 'lodash/unset';
import { cloneDeep } from 'lodash';
import set from 'lodash/set';
import union from 'lodash/union';
-import { fuzzyCompare } from '../../utils/utilities';
+import { fuzzyCompare } from '@utils/utilities';
type PairToMatch = {
field1: string;
diff --git a/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts b/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts
index 6bc61ee8ac119..689881910e025 100644
--- a/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts
+++ b/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts
@@ -11,7 +11,7 @@ import {
getItemCopy,
getItemsCopy,
pgInsert,
- pgQuery,
+ pgQueryV2,
pgUpdate,
} from '../Postgres/v1/genericFunctions';
@@ -73,9 +73,10 @@ export class CrateDb implements INodeType {
displayName: 'Query',
name: 'query',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
- sqlDialect: 'postgres',
+ sqlDialect: 'PostgreSQL',
},
displayOptions: {
show: {
@@ -283,13 +284,9 @@ export class CrateDb implements INodeType {
// executeQuery
// ----------------------------------
- const queryResult = await pgQuery(
- this.getNodeParameter,
- pgp,
- db,
- items,
- this.continueOnFail(),
- );
+ const queryResult = await pgQueryV2.call(this, pgp, db, items, this.continueOnFail(), {
+ resolveExpression: true,
+ });
returnItems = this.helpers.returnJsonArray(queryResult);
} else if (operation === 'insert') {
diff --git a/packages/nodes-base/nodes/EmailSend/v2/send.operation.ts b/packages/nodes-base/nodes/EmailSend/v2/send.operation.ts
index 0c2dda97ed481..3a80e306c634f 100644
--- a/packages/nodes-base/nodes/EmailSend/v2/send.operation.ts
+++ b/packages/nodes-base/nodes/EmailSend/v2/send.operation.ts
@@ -10,7 +10,7 @@ import { NodeApiError } from 'n8n-workflow';
import { createTransport } from 'nodemailer';
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
-import { updateDisplayOptions } from '../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
const properties: INodeProperties[] = [
// TODO: Add choice for text as text or html (maybe also from name)
diff --git a/packages/nodes-base/nodes/Google/Analytics/v1/GoogleAnalyticsV1.node.ts b/packages/nodes-base/nodes/Google/Analytics/v1/GoogleAnalyticsV1.node.ts
index e2977a6d49bef..04d668464bbb0 100644
--- a/packages/nodes-base/nodes/Google/Analytics/v1/GoogleAnalyticsV1.node.ts
+++ b/packages/nodes-base/nodes/Google/Analytics/v1/GoogleAnalyticsV1.node.ts
@@ -16,7 +16,7 @@ import { googleApiRequest, googleApiRequestAllItems, merge, simplify } from './G
import moment from 'moment-timezone';
import type { IData } from './Interfaces';
-import { oldVersionNotice } from '../../../../utils/descriptions';
+import { oldVersionNotice } from '@utils/descriptions';
const versionDescription: INodeTypeDescription = {
displayName: 'Google Analytics',
diff --git a/packages/nodes-base/nodes/Google/BigQuery/v1/GoogleBigQueryV1.node.ts b/packages/nodes-base/nodes/Google/BigQuery/v1/GoogleBigQueryV1.node.ts
index 394e32c6ada48..748aaad4499f8 100644
--- a/packages/nodes-base/nodes/Google/BigQuery/v1/GoogleBigQueryV1.node.ts
+++ b/packages/nodes-base/nodes/Google/BigQuery/v1/GoogleBigQueryV1.node.ts
@@ -20,7 +20,7 @@ import { recordFields, recordOperations } from './RecordDescription';
import { v4 as uuid } from 'uuid';
-import { oldVersionNotice } from '../../../../utils/descriptions';
+import { oldVersionNotice } from '@utils/descriptions';
const versionDescription: INodeTypeDescription = {
displayName: 'Google BigQuery',
diff --git a/packages/nodes-base/nodes/Google/BigQuery/v2/actions/database/executeQuery.operation.ts b/packages/nodes-base/nodes/Google/BigQuery/v2/actions/database/executeQuery.operation.ts
index 0e78130098a31..7a73c36ab811f 100644
--- a/packages/nodes-base/nodes/Google/BigQuery/v2/actions/database/executeQuery.operation.ts
+++ b/packages/nodes-base/nodes/Google/BigQuery/v2/actions/database/executeQuery.operation.ts
@@ -3,7 +3,7 @@ import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError, sleep } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { getResolvables, updateDisplayOptions } from '@utils/utilities';
import type { JobInsertResponse } from '../../helpers/interfaces';
import { prepareOutput } from '../../helpers/utils';
@@ -14,6 +14,7 @@ const properties: INodeProperties[] = [
displayName: 'SQL Query',
name: 'sqlQuery',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
},
@@ -31,6 +32,7 @@ const properties: INodeProperties[] = [
displayName: 'SQL Query',
name: 'sqlQuery',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
},
@@ -160,12 +162,16 @@ export async function execute(this: IExecuteFunctions): Promise string | undefined;
diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts
index 57483e58295b3..78288365639bb 100644
--- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts
+++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts
@@ -24,7 +24,7 @@ import {
replaceNullValues,
sanitizeUiMessage,
} from '../GenericFunctions';
-import { keysToLowercase } from '../../../utils/utilities';
+import { keysToLowercase } from '@utils/utilities';
function toText(data: T) {
if (typeof data === 'object' && data !== null) {
diff --git a/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts b/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts
index 50114a9041ae4..d0f10e29b21df 100644
--- a/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts
+++ b/packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts
@@ -12,7 +12,7 @@ import type {
} from 'n8n-workflow';
import { deepCopy } from 'n8n-workflow';
-import { oldVersionNotice } from '../../../utils/descriptions';
+import { oldVersionNotice } from '@utils/descriptions';
const versionDescription: INodeTypeDescription = {
displayName: 'Merge',
diff --git a/packages/nodes-base/nodes/Merge/v2/GenericFunctions.ts b/packages/nodes-base/nodes/Merge/v2/GenericFunctions.ts
index 88cc5f24a4033..19f2f8bffb006 100644
--- a/packages/nodes-base/nodes/Merge/v2/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/Merge/v2/GenericFunctions.ts
@@ -11,7 +11,7 @@ import assignWith from 'lodash/assignWith';
import get from 'lodash/get';
import merge from 'lodash/merge';
import mergeWith from 'lodash/mergeWith';
-import { fuzzyCompare } from '../../../utils/utilities';
+import { fuzzyCompare } from '@utils/utilities';
type PairToMatch = {
field1: string;
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/addTable.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/addTable.operation.ts
index da1d44554720a..6e575516c2dfb 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/addTable.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/addTable.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/append.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/append.operation.ts
index e97b2d18e405f..3d335e88a5c56 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/append.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/append.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { processJsonInput, updateDisplayOptions } from '../../../../../../utils/utilities';
+import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse } from '../../helpers/interfaces';
import { prepareOutput } from '../../helpers/utils';
import { microsoftApiRequest } from '../../transport';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/convertToRange.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/convertToRange.operation.ts
index 281b15461d0df..f5a9337710f1d 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/convertToRange.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/convertToRange.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { tableRLC, workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/deleteTable.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/deleteTable.operation.ts
index 171c80044c9d5..367b5ed3bf643 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/deleteTable.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/deleteTable.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { tableRLC, workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getColumns.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getColumns.operation.ts
index 18260d84d254d..ea49a70356a1d 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getColumns.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getColumns.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest, microsoftApiRequestAllItemsSkip } from '../../transport';
import { tableRLC, workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getRows.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getRows.operation.ts
index bc0c56f940365..41a48f0fd278e 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getRows.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/getRows.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest, microsoftApiRequestAllItemsSkip } from '../../transport';
import { tableRLC, workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/lookup.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/lookup.operation.ts
index 6229930ad88cc..cbfa515d90e00 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/lookup.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/table/lookup.operation.ts
@@ -1,7 +1,7 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties, JsonObject } from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequestAllItemsSkip } from '../../transport';
import { tableRLC, workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/addWorksheet.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/addWorksheet.operation.ts
index 856a909f28874..ec8701723c52e 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/addWorksheet.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/addWorksheet.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { workbookRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/deleteWorkbook.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/deleteWorkbook.operation.ts
index b97acce63a518..15dc65335bf97 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/deleteWorkbook.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/deleteWorkbook.operation.ts
@@ -1,7 +1,7 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { workbookRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/getAll.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/getAll.operation.ts
index bcff50920a95a..0c24643f5fba0 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/getAll.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/workbook/getAll.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest, microsoftApiRequestAllItems } from '../../transport';
const properties: INodeProperties[] = [
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/append.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/append.operation.ts
index 7cb57d6782e97..b572b69a139db 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/append.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/append.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { processJsonInput, updateDisplayOptions } from '../../../../../../utils/utilities';
+import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse } from '../../helpers/interfaces';
import { prepareOutput } from '../../helpers/utils';
import { microsoftApiRequest } from '../../transport';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/clear.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/clear.operation.ts
index 4e9b5ab8cbce7..36205d4a60f5f 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/clear.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/clear.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/deleteWorksheet.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/deleteWorksheet.operation.ts
index e9305e219ffd1..4d9bc49f06d2a 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/deleteWorksheet.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/deleteWorksheet.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest } from '../../transport';
import { workbookRLC, worksheetRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/getAll.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/getAll.operation.ts
index 16cc37fab04cc..e69d59767cace 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/getAll.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/getAll.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import { microsoftApiRequest, microsoftApiRequestAllItems } from '../../transport';
import { workbookRLC } from '../common.descriptions';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/readRows.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/readRows.operation.ts
index eeb791c1ae2b9..7b8e095de12fe 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/readRows.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/readRows.operation.ts
@@ -1,6 +1,6 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse } from '../../helpers/interfaces';
import { prepareOutput } from '../../helpers/utils';
import { microsoftApiRequest } from '../../transport';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/update.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/update.operation.ts
index 58805994c6cb0..8ac73272eb35a 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/update.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/update.operation.ts
@@ -1,7 +1,7 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { processJsonInput, updateDisplayOptions } from '../../../../../../utils/utilities';
+import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces';
import { prepareOutput, updateByAutoMaping, updateByDefinedValues } from '../../helpers/utils';
import { microsoftApiRequest } from '../../transport';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/upsert.operation.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/upsert.operation.ts
index fa635aac8385e..160ef5ba53069 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/upsert.operation.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/actions/worksheet/upsert.operation.ts
@@ -1,7 +1,7 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { processJsonInput, updateDisplayOptions } from '../../../../../../utils/utilities';
+import { processJsonInput, updateDisplayOptions } from '@utils/utilities';
import type { ExcelResponse, UpdateSummary } from '../../helpers/interfaces';
import { prepareOutput, updateByAutoMaping, updateByDefinedValues } from '../../helpers/utils';
import { microsoftApiRequest } from '../../transport';
diff --git a/packages/nodes-base/nodes/Microsoft/Excel/v2/helpers/utils.ts b/packages/nodes-base/nodes/Microsoft/Excel/v2/helpers/utils.ts
index 650ac8ad7fa68..1f71147c3d287 100644
--- a/packages/nodes-base/nodes/Microsoft/Excel/v2/helpers/utils.ts
+++ b/packages/nodes-base/nodes/Microsoft/Excel/v2/helpers/utils.ts
@@ -3,7 +3,7 @@ import type { IDataObject, INode, INodeExecutionData } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
import type { ExcelResponse, SheetData, UpdateSummary } from './interfaces';
import { constructExecutionMetaData } from 'n8n-core';
-import { wrapData } from '../../../../../utils/utilities';
+import { wrapData } from '@utils/utilities';
type PrepareOutputConfig = {
rawData: boolean;
diff --git a/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts b/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts
index 14a39fdddb455..9a0a3539600b4 100644
--- a/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts
+++ b/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts
@@ -11,7 +11,7 @@ import type {
} from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { chunk, flatten } from '../../../utils/utilities';
+import { chunk, flatten, getResolvables } from '@utils/utilities';
import mssql from 'mssql';
@@ -90,9 +90,10 @@ export class MicrosoftSql implements INodeType {
displayName: 'Query',
name: 'query',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
- sqlDialect: 'mssql',
+ sqlDialect: 'MSSQL',
},
displayOptions: {
show: {
@@ -293,7 +294,11 @@ export class MicrosoftSql implements INodeType {
// executeQuery
// ----------------------------------
- const rawQuery = this.getNodeParameter('query', 0) as string;
+ let rawQuery = this.getNodeParameter('query', 0) as string;
+
+ for (const resolvable of getResolvables(rawQuery)) {
+ rawQuery = rawQuery.replace(resolvable, this.evaluateExpression(resolvable, 0) as string);
+ }
const queryResult = await pool.request().query(rawQuery);
diff --git a/packages/nodes-base/nodes/MySql/v1/MySqlV1.node.ts b/packages/nodes-base/nodes/MySql/v1/MySqlV1.node.ts
index 8938fb48f8798..ab25667113674 100644
--- a/packages/nodes-base/nodes/MySql/v1/MySqlV1.node.ts
+++ b/packages/nodes-base/nodes/MySql/v1/MySqlV1.node.ts
@@ -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: {
diff --git a/packages/nodes-base/nodes/MySql/v2/actions/database/deleteTable.operation.ts b/packages/nodes-base/nodes/MySql/v2/actions/database/deleteTable.operation.ts
index 09cadea31344e..ef6808ca98594 100644
--- a/packages/nodes-base/nodes/MySql/v2/actions/database/deleteTable.operation.ts
+++ b/packages/nodes-base/nodes/MySql/v2/actions/database/deleteTable.operation.ts
@@ -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';
diff --git a/packages/nodes-base/nodes/MySql/v2/actions/database/executeQuery.operation.ts b/packages/nodes-base/nodes/MySql/v2/actions/database/executeQuery.operation.ts
index 853be02ac3822..13c552b0a1a3a 100644
--- a/packages/nodes-base/nodes/MySql/v2/actions/database/executeQuery.operation.ts
+++ b/packages/nodes-base/nodes/MySql/v2/actions/database/executeQuery.operation.ts
@@ -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, {});
diff --git a/packages/nodes-base/nodes/MySql/v2/actions/database/insert.operation.ts b/packages/nodes-base/nodes/MySql/v2/actions/database/insert.operation.ts
index ce5c523c66ae4..08d818d31f64f 100644
--- a/packages/nodes-base/nodes/MySql/v2/actions/database/insert.operation.ts
+++ b/packages/nodes-base/nodes/MySql/v2/actions/database/insert.operation.ts
@@ -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';
diff --git a/packages/nodes-base/nodes/MySql/v2/actions/database/select.operation.ts b/packages/nodes-base/nodes/MySql/v2/actions/database/select.operation.ts
index 5afbe3151321b..909de912f66ac 100644
--- a/packages/nodes-base/nodes/MySql/v2/actions/database/select.operation.ts
+++ b/packages/nodes-base/nodes/MySql/v2/actions/database/select.operation.ts
@@ -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';
diff --git a/packages/nodes-base/nodes/MySql/v2/actions/database/update.operation.ts b/packages/nodes-base/nodes/MySql/v2/actions/database/update.operation.ts
index b3620e0c4b122..7dd602e77f47c 100644
--- a/packages/nodes-base/nodes/MySql/v2/actions/database/update.operation.ts
+++ b/packages/nodes-base/nodes/MySql/v2/actions/database/update.operation.ts
@@ -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';
diff --git a/packages/nodes-base/nodes/MySql/v2/actions/database/upsert.operation.ts b/packages/nodes-base/nodes/MySql/v2/actions/database/upsert.operation.ts
index dd50f20ba17eb..859686e5d651e 100644
--- a/packages/nodes-base/nodes/MySql/v2/actions/database/upsert.operation.ts
+++ b/packages/nodes-base/nodes/MySql/v2/actions/database/upsert.operation.ts
@@ -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';
diff --git a/packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts b/packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts
index ead4afb90db7f..09d57ad9fcc60 100644
--- a/packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts
+++ b/packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts
@@ -16,7 +16,7 @@ import pgPromise from 'pg-promise';
import { pgInsertV2, pgQueryV2, pgUpdate, wrapData } from './genericFunctions';
-import { oldVersionNotice } from '../../../utils/descriptions';
+import { oldVersionNotice } from '@utils/descriptions';
const versionDescription: INodeTypeDescription = {
displayName: 'Postgres',
@@ -74,9 +74,10 @@ const versionDescription: INodeTypeDescription = {
displayName: 'Query',
name: 'query',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
- sqlDialect: 'postgres',
+ sqlDialect: 'PostgreSQL',
},
displayOptions: {
show: {
diff --git a/packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts b/packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts
index bf8548f0222b1..edf4f02a625b5 100644
--- a/packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts
+++ b/packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts
@@ -1,6 +1,7 @@
import type { IExecuteFunctions, IDataObject, INodeExecutionData, JsonObject } from 'n8n-workflow';
import type pgPromise from 'pg-promise';
import type pg from 'pg-promise/typescript/pg-subset';
+import { getResolvables } from '@utils/utilities';
/**
* Returns of a shallow copy of the items which only contains the json data and
@@ -168,7 +169,10 @@ export async function pgQueryV2(
db: pgPromise.IDatabase<{}, pg.IClient>,
items: INodeExecutionData[],
continueOnFail: boolean,
- overrideMode?: string,
+ options?: {
+ overrideMode?: string;
+ resolveExpression?: boolean;
+ },
): Promise {
const additionalFields = this.getNodeParameter('additionalFields', 0);
@@ -183,13 +187,22 @@ export async function pgQueryV2(
type QueryWithValues = { query: string; values?: string[] };
const allQueries = new Array();
for (let i = 0; i < items.length; i++) {
- const query = this.getNodeParameter('query', i) as string;
+ let query = this.getNodeParameter('query', i) as string;
+
+ if (options?.resolveExpression) {
+ for (const resolvable of getResolvables(query)) {
+ query = query.replace(resolvable, this.evaluateExpression(resolvable, i) as string);
+ }
+ }
+
const values = valuesArray[i];
const queryFormat = { query, values };
allQueries.push(queryFormat);
}
- const mode = overrideMode ? overrideMode : ((additionalFields.mode ?? 'multiple') as string);
+ const mode = options?.overrideMode
+ ? options.overrideMode
+ : ((additionalFields.mode ?? 'multiple') as string);
if (mode === 'multiple') {
return (await db.multi(pgp.helpers.concat(allQueries)))
.map((result, i) => {
diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts
index c0d4eba9a4320..40c205cc4ef35 100644
--- a/packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts
+++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts
@@ -2,7 +2,7 @@ import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import type {
PgpDatabase,
diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts
index 1d59228f0b98c..8d3346ccc9589 100644
--- a/packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts
+++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts
@@ -2,7 +2,7 @@ import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../utils/utilities';
+import { getResolvables, updateDisplayOptions } from '@utils/utilities';
import type { PgpDatabase, QueriesRunner, QueryWithValues } from '../../helpers/interfaces';
@@ -17,18 +17,19 @@ const properties: INodeProperties[] = [
type: 'string',
default: '',
placeholder: 'e.g. SELECT id, name FROM product WHERE quantity > $1 AND price <= $2',
+ noDataExpression: true,
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.",
typeOptions: {
editor: 'sqlEditor',
- sqlDialect: 'postgres',
+ sqlDialect: 'PostgreSQL',
},
hint: 'Prefer using query parameters over n8n expressions to avoid SQL injection attacks',
},
{
displayName: `
- To use query parameters in your SQL query, reference them as $1, $2, $3, etc in the corresponding order. More info.
+ To use query parameters in your SQL query, reference them as $1, $2, $3, etc in the corresponding order. More info.
`,
name: 'notice',
type: 'notice',
@@ -58,7 +59,11 @@ export async function execute(
const queries: QueryWithValues[] = [];
for (let i = 0; i < items.length; i++) {
- const query = this.getNodeParameter('query', i) as string;
+ let query = this.getNodeParameter('query', i) as string;
+
+ for (const resolvable of getResolvables(query)) {
+ query = query.replace(resolvable, this.evaluateExpression(resolvable, i) as string);
+ }
let values: IDataObject[] = [];
diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts
index 3fbecdee548c2..e6a67f4100db6 100644
--- a/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts
+++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts
@@ -1,7 +1,7 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import type {
PgpDatabase,
diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts
index 2844893dc9959..80a9418880434 100644
--- a/packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts
+++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts
@@ -1,7 +1,7 @@
import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import type {
PgpDatabase,
diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts
index 4b1f9c4c9d18b..32413a94e1961 100644
--- a/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts
+++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts
@@ -2,7 +2,7 @@ import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import type {
PgpDatabase,
diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts
index 10a68c654154d..8fcbaa6f87792 100644
--- a/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts
+++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts
@@ -2,7 +2,7 @@ import type { IExecuteFunctions } from 'n8n-core';
import type { IDataObject, INodeExecutionData, INodeProperties } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { updateDisplayOptions } from '../../../../../utils/utilities';
+import { updateDisplayOptions } from '@utils/utilities';
import type {
PgpDatabase,
diff --git a/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts b/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts
index 90af31d753afa..9090243607d9d 100644
--- a/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts
+++ b/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts
@@ -8,7 +8,7 @@ import { NodeOperationError } from 'n8n-workflow';
import pgPromise from 'pg-promise';
-import { pgInsert, pgQuery } from '../Postgres/v1/genericFunctions';
+import { pgInsert, pgQueryV2 } from '../Postgres/v1/genericFunctions';
export class QuestDb implements INodeType {
description: INodeTypeDescription = {
@@ -60,9 +60,10 @@ export class QuestDb implements INodeType {
displayName: 'Query',
name: 'query',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
- sqlDialect: 'postgres',
+ sqlDialect: 'PostgreSQL',
},
displayOptions: {
show: {
@@ -225,14 +226,10 @@ export class QuestDb implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', 0);
const mode = (additionalFields.mode || 'independently') as string;
- const queryResult = await pgQuery(
- this.getNodeParameter,
- pgp,
- db,
- items,
- this.continueOnFail(),
- mode,
- );
+ const queryResult = await pgQueryV2.call(this, pgp, db, items, this.continueOnFail(), {
+ overrideMode: mode,
+ resolveExpression: true,
+ });
returnItems = this.helpers.returnJsonArray(queryResult);
} else if (operation === 'insert') {
diff --git a/packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts b/packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts
index 6bf2d6afcff49..81431612391ec 100644
--- a/packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts
+++ b/packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts
@@ -22,7 +22,7 @@ import { userProfileFields, userProfileOperations } from './UserProfileDescripti
import { slackApiRequest, slackApiRequestAllItems, validateJSON } from './GenericFunctions';
import type { IAttachment } from './MessageInterface';
-import { oldVersionNotice } from '../../../utils/descriptions';
+import { oldVersionNotice } from '@utils/descriptions';
import moment from 'moment';
diff --git a/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts b/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts
index 32ea9e477ff65..77101ee04629c 100644
--- a/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts
+++ b/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts
@@ -9,6 +9,7 @@ import type {
import { connect, copyInputItems, destroy, execute } from './GenericFunctions';
import snowflake from 'snowflake-sdk';
+import { getResolvables } from '@utils/utilities';
export class Snowflake implements INodeType {
description: INodeTypeDescription = {
@@ -65,6 +66,7 @@ export class Snowflake implements INodeType {
displayName: 'Query',
name: 'query',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
},
@@ -178,7 +180,12 @@ export class Snowflake implements INodeType {
// ----------------------------------
for (let i = 0; i < items.length; i++) {
- const query = this.getNodeParameter('query', i) as string;
+ let query = this.getNodeParameter('query', i) as string;
+
+ for (const resolvable of getResolvables(query)) {
+ query = query.replace(resolvable, this.evaluateExpression(resolvable, i) as string);
+ }
+
responseData = await execute(connection, query, []);
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as IDataObject[]),
diff --git a/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts b/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts
index 1d0c2c21ac650..10e8259d288f8 100644
--- a/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts
+++ b/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts
@@ -6,7 +6,7 @@ import type {
} from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
-import { pgInsert, pgQuery, pgUpdate } from '../Postgres/v1/genericFunctions';
+import { pgInsert, pgQueryV2, pgUpdate } from '../Postgres/v1/genericFunctions';
import pgPromise from 'pg-promise';
@@ -65,9 +65,10 @@ export class TimescaleDb implements INodeType {
displayName: 'Query',
name: 'query',
type: 'string',
+ noDataExpression: true,
typeOptions: {
editor: 'sqlEditor',
- sqlDialect: 'postgres',
+ sqlDialect: 'PostgreSQL',
},
displayOptions: {
show: {
@@ -279,13 +280,9 @@ export class TimescaleDb implements INodeType {
// executeQuery
// ----------------------------------
- const queryResult = await pgQuery(
- this.getNodeParameter,
- pgp,
- db,
- items,
- this.continueOnFail(),
- );
+ const queryResult = await pgQueryV2.call(this, pgp, db, items, this.continueOnFail(), {
+ resolveExpression: true,
+ });
returnItems = this.helpers.returnJsonArray(queryResult);
} else if (operation === 'insert') {
diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json
index 1f9608e46d67c..e260be8b82135 100644
--- a/packages/nodes-base/package.json
+++ b/packages/nodes-base/package.json
@@ -17,7 +17,7 @@
"clean": "rimraf dist .turbo",
"dev": "pnpm watch",
"typecheck": "tsc",
- "build": "tsc -p tsconfig.build.json && gulp build:icons && gulp build:translations && pnpm build:metadata",
+ "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && gulp build:icons && gulp build:translations && pnpm build:metadata",
"build:translations": "gulp build:translations",
"build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types",
"format": "prettier --write . --ignore-path ../../.prettierignore",
diff --git a/packages/nodes-base/test/utils/utilities.test.ts b/packages/nodes-base/test/utils/utilities.test.ts
index e98ca10b20011..88edcedc279ce 100644
--- a/packages/nodes-base/test/utils/utilities.test.ts
+++ b/packages/nodes-base/test/utils/utilities.test.ts
@@ -1,4 +1,4 @@
-import { fuzzyCompare, keysToLowercase, wrapData } from '../../utils/utilities';
+import { fuzzyCompare, getResolvables, keysToLowercase, wrapData } from '@utils/utilities';
//most test cases for fuzzyCompare are done in Compare Datasets node tests
describe('Test fuzzyCompare', () => {
@@ -101,3 +101,39 @@ describe('Test keysToLowercase', () => {
expect(test6).toEqual(undefined);
});
});
+
+describe('Test getResolvables', () => {
+ it('should return empty array when there are no resolvables', () => {
+ expect(getResolvables('Plain String, no resolvables here.')).toEqual([]);
+ });
+ it('should properly handle resovables in SQL query', () => {
+ expect(getResolvables('SELECT * FROM {{ $json.db }}.{{ $json.table }};')).toEqual([
+ '{{ $json.db }}',
+ '{{ $json.table }}',
+ ]);
+ });
+ it('should properly handle resovables in HTML string', () => {
+ expect(
+ getResolvables(
+ `
+
+
+ {{ $json.pageTitle }}
+ {{ $json.heading }}
+
+
+
+ `,
+ ),
+ ).toEqual([
+ '{{ $json.pageTitle }}',
+ '{{ $json.heading }}',
+ '{{ $json.pageHeight }}',
+ '{{ $json.welcomeMessage }}',
+ ]);
+ });
+});
diff --git a/packages/nodes-base/tsconfig.json b/packages/nodes-base/tsconfig.json
index 6caa6cf9bb494..2d53507ba0562 100644
--- a/packages/nodes-base/tsconfig.json
+++ b/packages/nodes-base/tsconfig.json
@@ -5,7 +5,8 @@
"types": ["node", "jest"],
"noEmit": true,
"paths": {
- "@test/*": ["./test/*"]
+ "@test/*": ["./test/*"],
+ "@utils/*": ["./utils/*"]
},
// TODO: remove all options below this line
"noImplicitReturns": false,
@@ -16,5 +17,12 @@
"references": [
{ "path": "../workflow/tsconfig.build.json" },
{ "path": "../core/tsconfig.build.json" }
- ]
+ ],
+ "tsc-alias": {
+ "replacers": {
+ "base-url": {
+ "enabled": false
+ }
+ }
+ }
}
diff --git a/packages/nodes-base/utils/utilities.ts b/packages/nodes-base/utils/utilities.ts
index cca0d35084680..4b7ce379899ee 100644
--- a/packages/nodes-base/utils/utilities.ts
+++ b/packages/nodes-base/utils/utilities.ts
@@ -214,3 +214,23 @@ export const keysToLowercase = (headers: T) => {
return acc;
}, {} as IDataObject);
};
+
+/**
+ * @TECH_DEBT Explore replacing with handlebars
+ */
+export function getResolvables(expression: string) {
+ if (!expression) return [];
+
+ const resolvables = [];
+ const resolvableRegex = /({{[\s\S]*?}})/g;
+
+ let match;
+
+ while ((match = resolvableRegex.exec(expression)) !== null) {
+ if (match[1]) {
+ resolvables.push(match[1]);
+ }
+ }
+
+ return resolvables;
+}
diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts
index 2a944ddbe7ddd..df3216de2e665 100644
--- a/packages/workflow/src/Interfaces.ts
+++ b/packages/workflow/src/Interfaces.ts
@@ -1025,7 +1025,15 @@ export type CodeAutocompleteTypes = 'function' | 'functionItem';
export type EditorType = 'code' | 'codeNodeEditor' | 'htmlEditor' | 'sqlEditor' | 'json';
export type CodeNodeEditorLanguage = (typeof CODE_LANGUAGES)[number];
export type CodeExecutionMode = (typeof CODE_EXECUTION_MODES)[number];
-export type SQLDialect = 'mssql' | 'mysql' | 'postgres';
+export type SQLDialect =
+ | 'StandardSQL'
+ | 'PostgreSQL'
+ | 'MySQL'
+ | 'MariaSQL'
+ | 'MSSQL'
+ | 'SQLite'
+ | 'Cassandra'
+ | 'PLSQL';
export interface ILoadOptions {
routing?: {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8082eaafff8f4..d15f941172942 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -773,9 +773,6 @@ importers:
'@codemirror/lang-python':
specifier: ^6.1.2
version: 6.1.2(@codemirror/state@6.1.4)(@codemirror/view@6.5.1)(@lezer/common@1.0.1)
- '@codemirror/lang-sql':
- specifier: ^6.4.1
- version: 6.4.1(@codemirror/view@6.5.1)(@lezer/common@1.0.1)
'@codemirror/language':
specifier: ^6.2.1
version: 6.2.1
@@ -818,6 +815,9 @@ importers:
'@jsplumb/util':
specifier: ^5.13.2
version: 5.13.2
+ '@n8n/codemirror-lang-sql':
+ specifier: ^1.0.0
+ version: 1.0.0(@codemirror/view@6.5.1)(@lezer/common@1.0.1)
axios:
specifier: ^0.21.1
version: 0.21.4
@@ -4128,19 +4128,6 @@ packages:
- '@lezer/common'
dev: false
- /@codemirror/lang-sql@6.4.1(@codemirror/view@6.5.1)(@lezer/common@1.0.1):
- resolution: {integrity: sha512-PFB56L+A0WGY35uRya+Trt5g19V9k2V9X3c55xoFW4RgiATr/yLqWsbbnEsdxuMn5tLpuikp7Kmj9smRsqBXAg==}
- dependencies:
- '@codemirror/autocomplete': 6.4.0(@codemirror/language@6.2.1)(@codemirror/state@6.1.4)(@codemirror/view@6.5.1)(@lezer/common@1.0.1)
- '@codemirror/language': 6.2.1
- '@codemirror/state': 6.1.4
- '@lezer/highlight': 1.1.1
- '@lezer/lr': 1.2.3
- transitivePeerDependencies:
- - '@codemirror/view'
- - '@lezer/common'
- dev: false
-
/@codemirror/language@6.2.1:
resolution: {integrity: sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==}
dependencies:
@@ -5272,6 +5259,19 @@ packages:
dev: false
optional: true
+ /@n8n/codemirror-lang-sql@1.0.0(@codemirror/view@6.5.1)(@lezer/common@1.0.1):
+ resolution: {integrity: sha512-7bmlhaSW+f/g+IarWbif/D9bUgwW8bjCbjfW6BCGqZHXTz9UQt8fM6tQ9MNh/3sZz9LPwcnT7XSSv73Ku0rriw==}
+ dependencies:
+ '@codemirror/autocomplete': 6.4.0(@codemirror/language@6.2.1)(@codemirror/state@6.1.4)(@codemirror/view@6.5.1)(@lezer/common@1.0.1)
+ '@codemirror/language': 6.2.1
+ '@codemirror/state': 6.1.4
+ '@lezer/highlight': 1.1.1
+ '@lezer/lr': 1.2.3
+ transitivePeerDependencies:
+ - '@codemirror/view'
+ - '@lezer/common'
+ dev: false
+
/@n8n_io/license-sdk@2.4.0:
resolution: {integrity: sha512-99kuCVH4NcBi4nyn/WIpd6KSIMLk/pbBks0zr8bC65ALKj0se7/2MwC6N+WwGkG7NqH0kMdGe/7Y5KnJkMTefg==}
engines: {node: '>=14.0.0', npm: '>=7.10.0'}