mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
chore: merge master
This commit is contained in:
commit
080a421f02
2
.github/workflows/e2e-tests-pr.yml
vendored
2
.github/workflows/e2e-tests-pr.yml
vendored
|
@ -47,5 +47,5 @@ jobs:
|
||||||
run: exit 0
|
run: exit 0
|
||||||
|
|
||||||
- name: Fail job if run-e2e-tests failed
|
- name: Fail job if run-e2e-tests failed
|
||||||
if: ${{ github.event.review.state != 'approved' || needs.run-e2e-tests.result == 'failure' }}
|
if: ${{ (github.event.review.state != 'approved' && github.event.review.state != 'commented') || needs.run-e2e-tests.result == 'failure' }}
|
||||||
run: exit 1
|
run: exit 1
|
||||||
|
|
|
@ -50,7 +50,7 @@ describe('NDV', () => {
|
||||||
workflowPage.getters.canvasNodes().last().dblclick();
|
workflowPage.getters.canvasNodes().last().dblclick();
|
||||||
ndv.getters.inputSelect().click();
|
ndv.getters.inputSelect().click();
|
||||||
ndv.getters.inputOption().last().click();
|
ndv.getters.inputOption().last().click();
|
||||||
ndv.getters.inputDataContainer().find('[class*=schema_]').should('exist')
|
ndv.getters.inputDataContainer().find('[class*=schema_]').should('exist');
|
||||||
ndv.getters.inputDataContainer().should('contain', 'start');
|
ndv.getters.inputDataContainer().should('contain', 'start');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -96,10 +96,20 @@ describe('NDV', () => {
|
||||||
ndv.getters.container().should('be.visible');
|
ndv.getters.container().should('be.visible');
|
||||||
workflowPage.actions.saveWorkflowUsingKeyboardShortcut();
|
workflowPage.actions.saveWorkflowUsingKeyboardShortcut();
|
||||||
workflowPage.getters.isWorkflowSaved();
|
workflowPage.getters.isWorkflowSaved();
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('test output schema view', () => {
|
describe('test output schema view', () => {
|
||||||
const schemaKeys = ['id', 'name', 'email', 'notes', 'country', 'created', 'objectValue', 'prop1', 'prop2'];
|
const schemaKeys = [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'email',
|
||||||
|
'notes',
|
||||||
|
'country',
|
||||||
|
'created',
|
||||||
|
'objectValue',
|
||||||
|
'prop1',
|
||||||
|
'prop2',
|
||||||
|
];
|
||||||
function setupSchemaWorkflow() {
|
function setupSchemaWorkflow() {
|
||||||
cy.createFixtureWorkflow('Test_workflow_schema_test.json', `NDV test schema view ${uuid()}`);
|
cy.createFixtureWorkflow('Test_workflow_schema_test.json', `NDV test schema view ${uuid()}`);
|
||||||
workflowPage.actions.zoomToFit();
|
workflowPage.actions.zoomToFit();
|
||||||
|
@ -108,41 +118,62 @@ describe('NDV', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should switch to output schema view and validate it', () => {
|
it('should switch to output schema view and validate it', () => {
|
||||||
setupSchemaWorkflow()
|
setupSchemaWorkflow();
|
||||||
ndv.getters.outputDisplayMode().children().should('have.length', 3);
|
ndv.getters.outputDisplayMode().children().should('have.length', 3);
|
||||||
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Table');
|
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Table');
|
||||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||||
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Schema');
|
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Schema');
|
||||||
|
|
||||||
schemaKeys.forEach((key) => {
|
schemaKeys.forEach((key) => {
|
||||||
ndv.getters.outputPanel().find('[data-test-id=run-data-schema-item]').contains(key).should('exist');
|
ndv.getters
|
||||||
|
.outputPanel()
|
||||||
|
.find('[data-test-id=run-data-schema-item]')
|
||||||
|
.contains(key)
|
||||||
|
.should('exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should preserve schema view after execution', () => {
|
it('should preserve schema view after execution', () => {
|
||||||
setupSchemaWorkflow()
|
setupSchemaWorkflow();
|
||||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||||
ndv.actions.execute();
|
ndv.actions.execute();
|
||||||
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Schema');
|
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Schema');
|
||||||
})
|
});
|
||||||
it('should collapse and expand nested schema object', () => {
|
it('should collapse and expand nested schema object', () => {
|
||||||
setupSchemaWorkflow()
|
setupSchemaWorkflow();
|
||||||
const expandedObjectProps = ['prop1', 'prop2'];;
|
const expandedObjectProps = ['prop1', 'prop2'];
|
||||||
const getObjectValueItem = () => ndv.getters.outputPanel().find('[data-test-id=run-data-schema-item]').filter(':contains("objectValue")');
|
const getObjectValueItem = () =>
|
||||||
|
ndv.getters
|
||||||
|
.outputPanel()
|
||||||
|
.find('[data-test-id=run-data-schema-item]')
|
||||||
|
.filter(':contains("objectValue")');
|
||||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||||
|
|
||||||
expandedObjectProps.forEach((key) => {
|
expandedObjectProps.forEach((key) => {
|
||||||
ndv.getters.outputPanel().find('[data-test-id=run-data-schema-item]').contains(key).should('be.visible');
|
ndv.getters
|
||||||
|
.outputPanel()
|
||||||
|
.find('[data-test-id=run-data-schema-item]')
|
||||||
|
.contains(key)
|
||||||
|
.should('be.visible');
|
||||||
});
|
});
|
||||||
getObjectValueItem().find('label').click();
|
getObjectValueItem().find('label').click();
|
||||||
expandedObjectProps.forEach((key) => {
|
expandedObjectProps.forEach((key) => {
|
||||||
ndv.getters.outputPanel().find('[data-test-id=run-data-schema-item]').contains(key).should('not.be.visible');
|
ndv.getters
|
||||||
|
.outputPanel()
|
||||||
|
.find('[data-test-id=run-data-schema-item]')
|
||||||
|
.contains(key)
|
||||||
|
.should('not.be.visible');
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
it('should not display pagination for schema', () => {
|
it('should not display pagination for schema', () => {
|
||||||
setupSchemaWorkflow()
|
setupSchemaWorkflow();
|
||||||
ndv.getters.backToCanvas().click();
|
ndv.getters.backToCanvas().click();
|
||||||
workflowPage.getters.canvasNodeByName('Set').click();
|
workflowPage.getters.canvasNodeByName('Set').click();
|
||||||
workflowPage.actions.addNodeToCanvas('Customer Datastore (n8n training)', true, true, 'Get All People');
|
workflowPage.actions.addNodeToCanvas(
|
||||||
|
'Customer Datastore (n8n training)',
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
'Get All People',
|
||||||
|
);
|
||||||
ndv.actions.execute();
|
ndv.actions.execute();
|
||||||
ndv.getters.outputPanel().contains('25 items').should('exist');
|
ndv.getters.outputPanel().contains('25 items').should('exist');
|
||||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
||||||
|
@ -150,9 +181,12 @@ describe('NDV', () => {
|
||||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
|
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
|
||||||
ndv.getters.outputDisplayMode().contains('JSON').click();
|
ndv.getters.outputDisplayMode().contains('JSON').click();
|
||||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
||||||
})
|
});
|
||||||
it('should display large schema', () => {
|
it('should display large schema', () => {
|
||||||
cy.createFixtureWorkflow('Test_workflow_schema_test_pinned_data.json', `NDV test schema view ${uuid()}`);
|
cy.createFixtureWorkflow(
|
||||||
|
'Test_workflow_schema_test_pinned_data.json',
|
||||||
|
`NDV test schema view ${uuid()}`,
|
||||||
|
);
|
||||||
workflowPage.actions.zoomToFit();
|
workflowPage.actions.zoomToFit();
|
||||||
workflowPage.actions.openNode('Set');
|
workflowPage.actions.openNode('Set');
|
||||||
|
|
||||||
|
@ -160,8 +194,11 @@ describe('NDV', () => {
|
||||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
||||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
|
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
|
||||||
ndv.getters.outputPanel().find('[data-test-id=run-data-schema-item] [data-test-id=run-data-schema-item]').should('have.length', 20);
|
ndv.getters
|
||||||
})
|
.outputPanel()
|
||||||
|
.find('[data-test-id=run-data-schema-item] [data-test-id=run-data-schema-item]')
|
||||||
|
.should('have.length', 20);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can link and unlink run selectors between input and output', () => {
|
it('can link and unlink run selectors between input and output', () => {
|
||||||
|
@ -170,11 +207,13 @@ describe('NDV', () => {
|
||||||
workflowPage.actions.executeWorkflow();
|
workflowPage.actions.executeWorkflow();
|
||||||
workflowPage.actions.openNode('Set3');
|
workflowPage.actions.openNode('Set3');
|
||||||
|
|
||||||
ndv.getters.inputRunSelector()
|
ndv.getters
|
||||||
|
.inputRunSelector()
|
||||||
.should('exist')
|
.should('exist')
|
||||||
.find('input')
|
.find('input')
|
||||||
.should('include.value', '2 of 2 (6 items)');
|
.should('include.value', '2 of 2 (6 items)');
|
||||||
ndv.getters.outputRunSelector()
|
ndv.getters
|
||||||
|
.outputRunSelector()
|
||||||
.should('exist')
|
.should('exist')
|
||||||
.find('input')
|
.find('input')
|
||||||
.should('include.value', '2 of 2 (6 items)');
|
.should('include.value', '2 of 2 (6 items)');
|
||||||
|
@ -183,23 +222,20 @@ describe('NDV', () => {
|
||||||
ndv.actions.switchOutputMode('Table');
|
ndv.actions.switchOutputMode('Table');
|
||||||
|
|
||||||
ndv.actions.changeOutputRunSelector('1 of 2 (6 items)');
|
ndv.actions.changeOutputRunSelector('1 of 2 (6 items)');
|
||||||
ndv.getters.inputRunSelector()
|
ndv.getters.inputRunSelector().find('input').should('include.value', '1 of 2 (6 items)');
|
||||||
.find('input')
|
|
||||||
.should('include.value', '1 of 2 (6 items)');
|
|
||||||
ndv.getters.inputTbodyCell(1, 0).should('have.text', '1111');
|
ndv.getters.inputTbodyCell(1, 0).should('have.text', '1111');
|
||||||
ndv.getters.outputTbodyCell(1, 0).should('have.text', '1111');
|
ndv.getters.outputTbodyCell(1, 0).should('have.text', '1111');
|
||||||
|
|
||||||
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
||||||
ndv.actions.changeInputRunSelector('2 of 2 (6 items)');
|
ndv.actions.changeInputRunSelector('2 of 2 (6 items)');
|
||||||
ndv.getters.outputRunSelector()
|
ndv.getters.outputRunSelector().find('input').should('include.value', '2 of 2 (6 items)');
|
||||||
.find('input')
|
|
||||||
.should('include.value', '2 of 2 (6 items)');
|
|
||||||
|
|
||||||
// unlink
|
// unlink
|
||||||
ndv.actions.toggleOutputRunLinking();
|
ndv.actions.toggleOutputRunLinking();
|
||||||
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
||||||
ndv.actions.changeOutputRunSelector('1 of 2 (6 items)');
|
ndv.actions.changeOutputRunSelector('1 of 2 (6 items)');
|
||||||
ndv.getters.inputRunSelector()
|
ndv.getters
|
||||||
|
.inputRunSelector()
|
||||||
.should('exist')
|
.should('exist')
|
||||||
.find('input')
|
.find('input')
|
||||||
.should('include.value', '2 of 2 (6 items)');
|
.should('include.value', '2 of 2 (6 items)');
|
||||||
|
@ -207,24 +243,18 @@ describe('NDV', () => {
|
||||||
// link again
|
// link again
|
||||||
ndv.actions.toggleOutputRunLinking();
|
ndv.actions.toggleOutputRunLinking();
|
||||||
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
||||||
ndv.getters.inputRunSelector()
|
ndv.getters.inputRunSelector().find('input').should('include.value', '1 of 2 (6 items)');
|
||||||
.find('input')
|
|
||||||
.should('include.value', '1 of 2 (6 items)');
|
|
||||||
|
|
||||||
// unlink again
|
// unlink again
|
||||||
ndv.actions.toggleInputRunLinking();
|
ndv.actions.toggleInputRunLinking();
|
||||||
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
||||||
ndv.actions.changeInputRunSelector('2 of 2 (6 items)');
|
ndv.actions.changeInputRunSelector('2 of 2 (6 items)');
|
||||||
ndv.getters.outputRunSelector()
|
ndv.getters.outputRunSelector().find('input').should('include.value', '1 of 2 (6 items)');
|
||||||
.find('input')
|
|
||||||
.should('include.value', '1 of 2 (6 items)');
|
|
||||||
|
|
||||||
// link again
|
// link again
|
||||||
ndv.actions.toggleInputRunLinking();
|
ndv.actions.toggleInputRunLinking();
|
||||||
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
ndv.getters.inputTbodyCell(1, 0).click(); // remove tooltip
|
||||||
ndv.getters.outputRunSelector()
|
ndv.getters.outputRunSelector().find('input').should('include.value', '2 of 2 (6 items)');
|
||||||
.find('input')
|
|
||||||
.should('include.value', '2 of 2 (6 items)');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display parameter hints correctly', () => {
|
it('should display parameter hints correctly', () => {
|
||||||
|
@ -247,21 +277,19 @@ describe('NDV', () => {
|
||||||
input: ' test',
|
input: ' test',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ' '
|
input: ' ',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: '<div></div>'
|
input: '<div></div>',
|
||||||
},
|
},
|
||||||
].forEach(({ input, output }) => {
|
].forEach(({ input, output }) => {
|
||||||
|
if (input) {
|
||||||
|
ndv.actions.typeIntoParameterInput('value', input);
|
||||||
|
}
|
||||||
|
ndv.getters.parameterInput('name').click(); // remove focus from input, hide expression preview
|
||||||
|
|
||||||
|
ndv.actions.validateExpressionPreview('value', output || input);
|
||||||
if (input) {
|
ndv.getters.parameterInput('value').clear();
|
||||||
ndv.actions.typeIntoParameterInput('value', input);
|
});
|
||||||
}
|
|
||||||
ndv.getters.parameterInput('name').click(); // remove focus from input, hide expression preview
|
|
||||||
|
|
||||||
ndv.actions.validateExpressionPreview('value', output || input);
|
|
||||||
ndv.getters.parameterInput('value').clear();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -77,22 +77,7 @@
|
||||||
"@types/json-diff": "^0.5.1",
|
"@types/json-diff": "^0.5.1",
|
||||||
"@types/jsonwebtoken": "^9.0.1",
|
"@types/jsonwebtoken": "^9.0.1",
|
||||||
"@types/localtunnel": "^1.9.0",
|
"@types/localtunnel": "^1.9.0",
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
"@types/lodash": "^4.14.195",
|
||||||
"@types/lodash.difference": "^4",
|
|
||||||
"@types/lodash.get": "^4.4.6",
|
|
||||||
"@types/lodash.intersection": "^4.4.7",
|
|
||||||
"@types/lodash.iteratee": "^4.7.7",
|
|
||||||
"@types/lodash.merge": "^4.6.6",
|
|
||||||
"@types/lodash.omit": "^4.5.7",
|
|
||||||
"@types/lodash.pick": "^4.4.7",
|
|
||||||
"@types/lodash.remove": "^4.7.7",
|
|
||||||
"@types/lodash.set": "^4.3.6",
|
|
||||||
"@types/lodash.split": "^4.4.7",
|
|
||||||
"@types/lodash.unionby": "^4.8.7",
|
|
||||||
"@types/lodash.uniq": "^4.5.7",
|
|
||||||
"@types/lodash.uniqby": "^4.7.7",
|
|
||||||
"@types/lodash.unset": "^4.5.7",
|
|
||||||
"@types/lodash.without": "^4.4.7",
|
|
||||||
"@types/parseurl": "^1.3.1",
|
"@types/parseurl": "^1.3.1",
|
||||||
"@types/passport-jwt": "^3.0.6",
|
"@types/passport-jwt": "^3.0.6",
|
||||||
"@types/psl": "^1.1.0",
|
"@types/psl": "^1.1.0",
|
||||||
|
@ -109,7 +94,6 @@
|
||||||
"@types/yamljs": "^0.2.31",
|
"@types/yamljs": "^0.2.31",
|
||||||
"chokidar": "^3.5.2",
|
"chokidar": "^3.5.2",
|
||||||
"concurrently": "^5.1.0",
|
"concurrently": "^5.1.0",
|
||||||
"lodash.debounce": "^4.0.8",
|
|
||||||
"mock-jwks": "^1.0.9",
|
"mock-jwks": "^1.0.9",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.2",
|
||||||
"run-script-os": "^1.0.7",
|
"run-script-os": "^1.0.7",
|
||||||
|
@ -161,21 +145,7 @@
|
||||||
"jwks-rsa": "^3.0.1",
|
"jwks-rsa": "^3.0.1",
|
||||||
"ldapts": "^4.2.6",
|
"ldapts": "^4.2.6",
|
||||||
"localtunnel": "^2.0.0",
|
"localtunnel": "^2.0.0",
|
||||||
"lodash.difference": "^4",
|
"lodash": "^4.17.21",
|
||||||
"lodash.get": "^4.4.2",
|
|
||||||
"lodash.intersection": "^4.4.0",
|
|
||||||
"lodash.iteratee": "^4.7.0",
|
|
||||||
"lodash.merge": "^4.6.2",
|
|
||||||
"lodash.omit": "^4.5.0",
|
|
||||||
"lodash.pick": "^4.4.0",
|
|
||||||
"lodash.remove": "^4.7.0",
|
|
||||||
"lodash.set": "^4.3.2",
|
|
||||||
"lodash.split": "^4.4.2",
|
|
||||||
"lodash.unionby": "^4.8.0",
|
|
||||||
"lodash.uniq": "^4.5.0",
|
|
||||||
"lodash.uniqby": "^4.7.0",
|
|
||||||
"lodash.unset": "^4.5.2",
|
|
||||||
"lodash.without": "^4.4.0",
|
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"mysql2": "~2.3.3",
|
"mysql2": "~2.3.3",
|
||||||
"n8n-core": "workspace:*",
|
"n8n-core": "workspace:*",
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
|
|
||||||
import { Credentials, NodeExecuteFunctions } from 'n8n-core';
|
import { Credentials, NodeExecuteFunctions } from 'n8n-core';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ICredentialDataDecryptedObject,
|
ICredentialDataDecryptedObject,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
import curlconverter from 'curlconverter';
|
import curlconverter from 'curlconverter';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import type { IDataObject } from 'n8n-workflow';
|
import type { IDataObject } from 'n8n-workflow';
|
||||||
import { jsonParse } from 'n8n-workflow';
|
import { jsonParse } from 'n8n-workflow';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import uniq from 'lodash.uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import type { DirectoryLoader, Types } from 'n8n-core';
|
import type { DirectoryLoader, Types } from 'n8n-core';
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { FindManyOptions, UpdateResult } from 'typeorm';
|
import type { FindManyOptions, UpdateResult } from 'typeorm';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import intersection from 'lodash.intersection';
|
import intersection from 'lodash/intersection';
|
||||||
import type { INode } from 'n8n-workflow';
|
import type { INode } from 'n8n-workflow';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ export const reloadNodesAndCredentials = async (
|
||||||
push: Push,
|
push: Push,
|
||||||
) => {
|
) => {
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const { default: debounce } = await import('lodash.debounce');
|
const { default: debounce } = await import('lodash/debounce');
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const { watch } = await import('chokidar');
|
const { watch } = await import('chokidar');
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
/* eslint-disable prefer-destructuring */
|
/* eslint-disable prefer-destructuring */
|
||||||
import type express from 'express';
|
import type express from 'express';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import stream from 'stream';
|
import stream from 'stream';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
|
|
||||||
|
@ -426,7 +426,7 @@ export async function executeWebhook(
|
||||||
const binaryData = (response.body as IDataObject)?.binaryData as IBinaryData;
|
const binaryData = (response.body as IDataObject)?.binaryData as IBinaryData;
|
||||||
if (binaryData?.id) {
|
if (binaryData?.id) {
|
||||||
res.header(response.headers);
|
res.header(response.headers);
|
||||||
const stream = NodeExecuteFunctions.getBinaryStream(binaryData.id);
|
const stream = BinaryDataManager.getInstance().getBinaryStream(binaryData.id);
|
||||||
void pipeline(stream, res).then(() =>
|
void pipeline(stream, res).then(() =>
|
||||||
responseCallback(null, { noWebhookResponse: true }),
|
responseCallback(null, { noWebhookResponse: true }),
|
||||||
);
|
);
|
||||||
|
@ -643,10 +643,12 @@ export async function executeWebhook(
|
||||||
if (!didSendResponse) {
|
if (!didSendResponse) {
|
||||||
// Send the webhook response manually
|
// Send the webhook response manually
|
||||||
res.setHeader('Content-Type', binaryData.mimeType);
|
res.setHeader('Content-Type', binaryData.mimeType);
|
||||||
const binaryDataBuffer = await BinaryDataManager.getInstance().retrieveBinaryData(
|
if (binaryData.id) {
|
||||||
binaryData,
|
const stream = BinaryDataManager.getInstance().getBinaryStream(binaryData.id);
|
||||||
);
|
await pipeline(stream, res);
|
||||||
res.end(binaryDataBuffer);
|
} else {
|
||||||
|
res.end(Buffer.from(binaryData.data, BINARY_ENCODING));
|
||||||
|
}
|
||||||
|
|
||||||
responseCallback(null, {
|
responseCallback(null, {
|
||||||
noWebhookResponse: true,
|
noWebhookResponse: true,
|
||||||
|
|
|
@ -42,7 +42,7 @@ import {
|
||||||
WorkflowHooks,
|
WorkflowHooks,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
import type { FindOptionsWhere } from 'typeorm';
|
import type { FindOptionsWhere } from 'typeorm';
|
||||||
import { LessThanOrEqual, In } from 'typeorm';
|
import { LessThanOrEqual, In } from 'typeorm';
|
||||||
import { DateUtils } from 'typeorm/util/DateUtils';
|
import { DateUtils } from 'typeorm/util/DateUtils';
|
||||||
|
|
|
@ -31,7 +31,7 @@ import config from '@/config';
|
||||||
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||||
import type { User } from '@db/entities/User';
|
import type { User } from '@db/entities/User';
|
||||||
import { RoleRepository } from '@db/repositories';
|
import { RoleRepository } from '@db/repositories';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
import { PermissionChecker } from './UserManagement/PermissionChecker';
|
import { PermissionChecker } from './UserManagement/PermissionChecker';
|
||||||
import { isWorkflowIdValid } from './utils';
|
import { isWorkflowIdValid } from './utils';
|
||||||
import { UserService } from './user/user.service';
|
import { UserService } from './user/user.service';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import type { ITaskData } from 'n8n-workflow';
|
||||||
import { sleep } from 'n8n-workflow';
|
import { sleep } from 'n8n-workflow';
|
||||||
import { sep } from 'path';
|
import { sep } from 'path';
|
||||||
import { diff } from 'json-diff';
|
import { diff } from 'json-diff';
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
|
|
||||||
import { ActiveExecutions } from '@/ActiveExecutions';
|
import { ActiveExecutions } from '@/ActiveExecutions';
|
||||||
import * as Db from '@/Db';
|
import * as Db from '@/Db';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
import { Authorized, Get, Post, Put, RestController } from '@/decorators';
|
import { Authorized, Get, Post, Put, RestController } from '@/decorators';
|
||||||
import { getLdapConfig, getLdapSynchronizations, updateLdapConfig } from '@/Ldap/helpers';
|
import { getLdapConfig, getLdapSynchronizations, updateLdapConfig } from '@/Ldap/helpers';
|
||||||
import { LdapService } from '@/Ldap/LdapService.ee';
|
import { LdapService } from '@/Ldap/LdapService.ee';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||||
import { Authorized, Post, RestController } from '@/decorators';
|
import { Authorized, Post, RestController } from '@/decorators';
|
||||||
|
|
|
@ -131,14 +131,14 @@ export class PasswordResetController {
|
||||||
|
|
||||||
const baseUrl = getInstanceBaseUrl();
|
const baseUrl = getInstanceBaseUrl();
|
||||||
const { id, firstName, lastName } = user;
|
const { id, firstName, lastName } = user;
|
||||||
const url = UserService.generatePasswordResetUrl(user);
|
const url = await UserService.generatePasswordResetUrl(user);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.mailer.passwordReset({
|
await this.mailer.passwordReset({
|
||||||
email,
|
email,
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
passwordResetUrl: url.toString(),
|
passwordResetUrl: url,
|
||||||
domain: baseUrl,
|
domain: baseUrl,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -2,11 +2,11 @@ import type { ClientOAuth2Options } from '@n8n/client-oauth2';
|
||||||
import { ClientOAuth2 } from '@n8n/client-oauth2';
|
import { ClientOAuth2 } from '@n8n/client-oauth2';
|
||||||
import Csrf from 'csrf';
|
import Csrf from 'csrf';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import split from 'lodash.split';
|
import split from 'lodash/split';
|
||||||
import unset from 'lodash.unset';
|
import unset from 'lodash/unset';
|
||||||
import { Credentials, UserSettings } from 'n8n-core';
|
import { Credentials, UserSettings } from 'n8n-core';
|
||||||
import type {
|
import type {
|
||||||
WorkflowExecuteMode,
|
WorkflowExecuteMode,
|
||||||
|
|
|
@ -29,7 +29,7 @@ import { WorkflowEntity } from '@/databases/entities/WorkflowEntity';
|
||||||
import { WorkflowTagMapping } from '@/databases/entities/WorkflowTagMapping';
|
import { WorkflowTagMapping } from '@/databases/entities/WorkflowTagMapping';
|
||||||
import { TagEntity } from '@/databases/entities/TagEntity';
|
import { TagEntity } from '@/databases/entities/TagEntity';
|
||||||
import { ActiveWorkflowRunner } from '../../ActiveWorkflowRunner';
|
import { ActiveWorkflowRunner } from '../../ActiveWorkflowRunner';
|
||||||
import without from 'lodash.without';
|
import without from 'lodash/without';
|
||||||
import type { VersionControllPullOptions } from './types/versionControlPullWorkFolder';
|
import type { VersionControllPullOptions } from './types/versionControlPullWorkFolder';
|
||||||
import { versionControlFoldersExistCheck } from './versionControlHelper.ee';
|
import { versionControlFoldersExistCheck } from './versionControlHelper.ee';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
messageEventBusDestinationFromDb,
|
messageEventBusDestinationFromDb,
|
||||||
incrementPrometheusMetric,
|
incrementPrometheusMetric,
|
||||||
} from '../MessageEventBusDestination/Helpers.ee';
|
} from '../MessageEventBusDestination/Helpers.ee';
|
||||||
import uniqby from 'lodash.uniqby';
|
import uniqby from 'lodash/uniqBy';
|
||||||
import type { EventMessageConfirmSource } from '../EventMessageClasses/EventMessageConfirm';
|
import type { EventMessageConfirmSource } from '../EventMessageClasses/EventMessageConfirm';
|
||||||
import type { EventMessageAuditOptions } from '../EventMessageClasses/EventMessageAudit';
|
import type { EventMessageAuditOptions } from '../EventMessageClasses/EventMessageAudit';
|
||||||
import { EventMessageAudit } from '../EventMessageClasses/EventMessageAudit';
|
import { EventMessageAudit } from '../EventMessageClasses/EventMessageAudit';
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Worker } from 'worker_threads';
|
||||||
import { createReadStream, existsSync, rmSync } from 'fs';
|
import { createReadStream, existsSync, rmSync } from 'fs';
|
||||||
import readline from 'readline';
|
import readline from 'readline';
|
||||||
import { jsonParse, LoggerProxy } from 'n8n-workflow';
|
import { jsonParse, LoggerProxy } from 'n8n-workflow';
|
||||||
import remove from 'lodash.remove';
|
import remove from 'lodash/remove';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { getEventMessageObjectByType } from '../EventMessageClasses/Helpers';
|
import { getEventMessageObjectByType } from '../EventMessageClasses/Helpers';
|
||||||
import type { EventMessageReturnMode } from '../MessageEventBus/MessageEventBus';
|
import type { EventMessageReturnMode } from '../MessageEventBus/MessageEventBus';
|
||||||
|
|
|
@ -4,7 +4,7 @@ import type { INode, IPinData, JsonObject } from 'n8n-workflow';
|
||||||
import { NodeApiError, jsonParse, LoggerProxy, Workflow } from 'n8n-workflow';
|
import { NodeApiError, jsonParse, LoggerProxy, Workflow } from 'n8n-workflow';
|
||||||
import type { FindOptionsSelect, FindOptionsWhere, UpdateResult } from 'typeorm';
|
import type { FindOptionsSelect, FindOptionsWhere, UpdateResult } from 'typeorm';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
|
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
|
||||||
import * as Db from '@/Db';
|
import * as Db from '@/Db';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { existsSync } from 'fs';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
import { CronJob } from 'cron';
|
import { CronJob } from 'cron';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import { BinaryDataManager, UserSettings } from 'n8n-core';
|
import { BinaryDataManager, UserSettings } from 'n8n-core';
|
||||||
import type {
|
import type {
|
||||||
ICredentialType,
|
ICredentialType,
|
||||||
|
|
|
@ -38,8 +38,7 @@
|
||||||
"@types/cron": "~1.7.1",
|
"@types/cron": "~1.7.1",
|
||||||
"@types/crypto-js": "^4.0.1",
|
"@types/crypto-js": "^4.0.1",
|
||||||
"@types/express": "^4.17.6",
|
"@types/express": "^4.17.6",
|
||||||
"@types/lodash.get": "^4.4.6",
|
"@types/lodash": "^4.14.195",
|
||||||
"@types/lodash.pick": "^4.4.7",
|
|
||||||
"@types/mime-types": "^2.1.0",
|
"@types/mime-types": "^2.1.0",
|
||||||
"@types/request-promise-native": "~1.0.15",
|
"@types/request-promise-native": "~1.0.15",
|
||||||
"@types/uuid": "^8.3.2"
|
"@types/uuid": "^8.3.2"
|
||||||
|
@ -54,8 +53,7 @@
|
||||||
"file-type": "^16.5.4",
|
"file-type": "^16.5.4",
|
||||||
"flatted": "^3.2.4",
|
"flatted": "^3.2.4",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash": "^4.17.21",
|
||||||
"lodash.pick": "^4.4.0",
|
|
||||||
"mime-types": "^2.1.27",
|
"mime-types": "^2.1.27",
|
||||||
"n8n-workflow": "workspace:*",
|
"n8n-workflow": "workspace:*",
|
||||||
"oauth-1.0a": "^2.2.6",
|
"oauth-1.0a": "^2.2.6",
|
||||||
|
|
|
@ -121,7 +121,7 @@ export class BinaryDataManager {
|
||||||
throw new Error('Storage mode used to store binary data not available');
|
throw new Error('Storage mode used to store binary data not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveBinaryData(binaryData: IBinaryData): Promise<Buffer> {
|
async getBinaryDataBuffer(binaryData: IBinaryData): Promise<Buffer> {
|
||||||
if (binaryData.id) {
|
if (binaryData.id) {
|
||||||
return this.retrieveBinaryDataByIdentifier(binaryData.id);
|
return this.retrieveBinaryDataByIdentifier(binaryData.id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ import {
|
||||||
validateFieldType,
|
validateFieldType,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
import { Agent } from 'https';
|
import { Agent } from 'https';
|
||||||
import { IncomingMessage } from 'http';
|
import { IncomingMessage } from 'http';
|
||||||
import { stringify } from 'qs';
|
import { stringify } from 'qs';
|
||||||
|
@ -92,7 +92,7 @@ import type {
|
||||||
} from '@n8n/client-oauth2';
|
} from '@n8n/client-oauth2';
|
||||||
import { ClientOAuth2 } from '@n8n/client-oauth2';
|
import { ClientOAuth2 } from '@n8n/client-oauth2';
|
||||||
import crypto, { createHmac } from 'crypto';
|
import crypto, { createHmac } from 'crypto';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import type { Request, Response } from 'express';
|
import type { Request, Response } from 'express';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
@ -747,6 +747,8 @@ function convertN8nRequestToAxios(n8nRequest: IHttpRequestOptions): AxiosRequest
|
||||||
auth,
|
auth,
|
||||||
proxy,
|
proxy,
|
||||||
url,
|
url,
|
||||||
|
maxBodyLength: Infinity,
|
||||||
|
maxContentLength: Infinity,
|
||||||
} as AxiosRequestConfig;
|
} as AxiosRequestConfig;
|
||||||
|
|
||||||
axiosRequest.params = n8nRequest.qs;
|
axiosRequest.params = n8nRequest.qs;
|
||||||
|
@ -915,7 +917,7 @@ export async function getBinaryDataBuffer(
|
||||||
inputIndex: number,
|
inputIndex: number,
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
const binaryData = inputData.main[inputIndex]![itemIndex]!.binary![propertyName]!;
|
const binaryData = inputData.main[inputIndex]![itemIndex]!.binary![propertyName]!;
|
||||||
return BinaryDataManager.getInstance().retrieveBinaryData(binaryData);
|
return BinaryDataManager.getInstance().getBinaryDataBuffer(binaryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,7 +37,7 @@ import type {
|
||||||
WorkflowExecuteMode,
|
WorkflowExecuteMode,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { LoggerProxy as Logger, WorkflowOperationError } from 'n8n-workflow';
|
import { LoggerProxy as Logger, WorkflowOperationError } from 'n8n-workflow';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import * as NodeExecuteFunctions from './NodeExecuteFunctions';
|
import * as NodeExecuteFunctions from './NodeExecuteFunctions';
|
||||||
|
|
||||||
export class WorkflowExecute {
|
export class WorkflowExecute {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ICredentialDataDecryptedObject,
|
ICredentialDataDecryptedObject,
|
||||||
|
|
|
@ -84,18 +84,6 @@ export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
label: `${prefix}jmespath()`,
|
label: `${prefix}jmespath()`,
|
||||||
info: this.$locale.baseText('codeNodeEditor.completer.$jmespath'),
|
info: this.$locale.baseText('codeNodeEditor.completer.$jmespath'),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: `${prefix}if()`,
|
|
||||||
info: this.$locale.baseText('codeNodeEditor.completer.$if'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: `${prefix}min()`,
|
|
||||||
info: this.$locale.baseText('codeNodeEditor.completer.$min'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: `${prefix}max()`,
|
|
||||||
info: this.$locale.baseText('codeNodeEditor.completer.$max'),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: `${prefix}runIndex`,
|
label: `${prefix}runIndex`,
|
||||||
info: this.$locale.baseText('codeNodeEditor.completer.$runIndex'),
|
info: this.$locale.baseText('codeNodeEditor.completer.$runIndex'),
|
||||||
|
|
|
@ -5,25 +5,35 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type { PropType } from 'vue';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import emitter from '@/mixins/emitter';
|
import type { EventBus } from 'n8n-design-system/utils';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'IntersectionObserved',
|
name: 'IntersectionObserved',
|
||||||
mixins: [emitter],
|
props: {
|
||||||
props: ['enabled'],
|
enabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
eventBus: {
|
||||||
|
type: Object as PropType<EventBus>,
|
||||||
|
default: () => createEventBus(),
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$dispatch('IntersectionObserver', 'observe', this.$refs.observed);
|
this.eventBus.emit('observe', this.$refs.observed);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
this.$dispatch('IntersectionObserver', 'unobserve', this.$refs.observed);
|
this.eventBus.emit('unobserve', this.$refs.observed);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,11 +5,27 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type { PropType } from 'vue';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import type { EventBus } from 'n8n-design-system/utils';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'IntersectionObserver',
|
name: 'IntersectionObserver',
|
||||||
props: ['threshold', 'enabled'],
|
props: {
|
||||||
|
threshold: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
enabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
eventBus: {
|
||||||
|
type: Object as PropType<EventBus>,
|
||||||
|
default: () => createEventBus(),
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
observer: null,
|
observer: null,
|
||||||
|
@ -35,13 +51,13 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
this.$data.observer = observer;
|
this.observer = observer;
|
||||||
|
|
||||||
this.$on('observe', (observed: Element) => {
|
this.eventBus.on('observe', (observed: Element) => {
|
||||||
observer.observe(observed);
|
observer.observe(observed);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$on('unobserve', (observed: Element) => {
|
this.eventBus.on('unobserve', (observed: Element) => {
|
||||||
observer.unobserve(observed);
|
observer.unobserve(observed);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,18 +38,6 @@
|
||||||
@update:modelValue="onInput"
|
@update:modelValue="onInput"
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
/>
|
/>
|
||||||
<n8n-info-tip v-if="!settingsStore.isSmtpSetup" class="mt-s">
|
|
||||||
<i18n path="settings.users.setupSMTPInfo">
|
|
||||||
<template #link>
|
|
||||||
<a
|
|
||||||
href="https://docs.n8n.io/reference/user-management.html#step-one-smtp"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ $locale.baseText('settings.users.setupSMTPInfo.link') }}
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</i18n>
|
|
||||||
</n8n-info-tip>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-if="!showInviteUrls" #footer>
|
<template v-if="!showInviteUrls" #footer>
|
||||||
<n8n-button
|
<n8n-button
|
||||||
|
|
|
@ -166,6 +166,7 @@ import type { IPermissions } from '@/permissions';
|
||||||
import { getWorkflowPermissions } from '@/permissions';
|
import { getWorkflowPermissions } from '@/permissions';
|
||||||
import { createEventBus } from 'n8n-design-system';
|
import { createEventBus } from 'n8n-design-system';
|
||||||
import { useCloudPlanStore } from '@/stores';
|
import { useCloudPlanStore } from '@/stores';
|
||||||
|
import { nodeViewEventBus } from '@/event-bus';
|
||||||
|
|
||||||
const hasChanged = (prev: string[], curr: string[]) => {
|
const hasChanged = (prev: string[], curr: string[]) => {
|
||||||
if (prev.length !== curr.length) {
|
if (prev.length !== curr.length) {
|
||||||
|
@ -445,7 +446,7 @@ export default defineComponent({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$root.$emit('importWorkflowData', { data: workflowData });
|
nodeViewEventBus.emit('importWorkflowData', { data: workflowData });
|
||||||
};
|
};
|
||||||
|
|
||||||
const inputRef = this.$refs.importFile as HTMLInputElement | undefined;
|
const inputRef = this.$refs.importFile as HTMLInputElement | undefined;
|
||||||
|
@ -505,7 +506,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
)) as MessageBoxInputData;
|
)) as MessageBoxInputData;
|
||||||
|
|
||||||
this.$root.$emit('importWorkflowUrl', { url: promptResponse.value });
|
nodeViewEventBus.emit('importWorkflowUrl', { url: promptResponse.value });
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -975,6 +975,8 @@ export default defineComponent({
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.node-settings {
|
.node-settings {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: var(--color-background-xlight);
|
background-color: var(--color-background-xlight);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -1007,7 +1009,6 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
.node-parameters-wrapper {
|
.node-parameters-wrapper {
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0 20px 200px 20px;
|
padding: 0 20px 200px 20px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
:droppable="droppable"
|
:droppable="droppable"
|
||||||
:node="node"
|
:node="node"
|
||||||
:path="path"
|
:path="path"
|
||||||
|
:event-bus="eventBus"
|
||||||
@input="valueChanged"
|
@input="valueChanged"
|
||||||
@modalOpenerClick="openExpressionEditorModal"
|
@modalOpenerClick="openExpressionEditorModal"
|
||||||
@focus="setFocus"
|
@focus="setFocus"
|
||||||
|
@ -390,8 +391,8 @@ import { useCredentialsStore } from '@/stores/credentials.store';
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
import { htmlEditorEventBus } from '@/event-bus';
|
import { htmlEditorEventBus } from '@/event-bus';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import type { EventBus } from 'n8n-design-system/utils';
|
||||||
type ResourceLocatorRef = InstanceType<typeof ResourceLocator>;
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'parameter-input',
|
name: 'parameter-input',
|
||||||
|
@ -462,6 +463,10 @@ export default defineComponent({
|
||||||
size: 'small',
|
size: 'small',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
eventBus: {
|
||||||
|
type: Object as PropType<EventBus>,
|
||||||
|
default: () => createEventBus(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -1111,9 +1116,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
} else if (command === 'refreshOptions') {
|
} else if (command === 'refreshOptions') {
|
||||||
if (this.isResourceLocatorParameter) {
|
if (this.isResourceLocatorParameter) {
|
||||||
const resourceLocatorRef = this.$refs.resourceLocator as ResourceLocatorRef | undefined;
|
this.eventBus.emit('refreshList');
|
||||||
|
|
||||||
resourceLocatorRef?.$emit('refreshList');
|
|
||||||
}
|
}
|
||||||
void this.loadRemoteParameterOptions();
|
void this.loadRemoteParameterOptions();
|
||||||
} else if (command === 'formatHtml') {
|
} else if (command === 'formatHtml') {
|
||||||
|
@ -1145,7 +1148,7 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$on('optionSelected', this.optionSelected);
|
this.eventBus.on('optionSelected', this.optionSelected);
|
||||||
|
|
||||||
this.tempValue = this.displayValue as string;
|
this.tempValue = this.displayValue as string;
|
||||||
if (this.node !== null) {
|
if (this.node !== null) {
|
||||||
|
@ -1185,6 +1188,9 @@ export default defineComponent({
|
||||||
inputFieldRef: this.$refs['inputField'],
|
inputFieldRef: this.$refs['inputField'],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.eventBus.off('optionSelected', this.optionSelected);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
:isForCredential="true"
|
:isForCredential="true"
|
||||||
:eventSource="eventSource"
|
:eventSource="eventSource"
|
||||||
:hint="!showRequiredErrors ? hint : ''"
|
:hint="!showRequiredErrors ? hint : ''"
|
||||||
|
:event-bus="eventBus"
|
||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
@textInput="valueChanged"
|
@textInput="valueChanged"
|
||||||
|
@ -65,6 +66,7 @@ import { isValueExpression } from '@/utils';
|
||||||
import type { INodeParameterResourceLocator, INodeProperties, IParameterLabel } from 'n8n-workflow';
|
import type { INodeParameterResourceLocator, INodeProperties, IParameterLabel } from 'n8n-workflow';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
type ParamRef = InstanceType<typeof ParameterInputWrapper>;
|
type ParamRef = InstanceType<typeof ParameterInputWrapper>;
|
||||||
|
|
||||||
|
@ -100,6 +102,7 @@ export default defineComponent({
|
||||||
focused: false,
|
focused: false,
|
||||||
blurredEver: false,
|
blurredEver: false,
|
||||||
menuExpanded: false,
|
menuExpanded: false,
|
||||||
|
eventBus: createEventBus(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -147,9 +150,7 @@ export default defineComponent({
|
||||||
this.menuExpanded = expanded;
|
this.menuExpanded = expanded;
|
||||||
},
|
},
|
||||||
optionSelected(command: string) {
|
optionSelected(command: string) {
|
||||||
if (this.$refs.param) {
|
this.eventBus.emit('optionSelected', command);
|
||||||
(this.$refs.param as ParamRef).$emit('optionSelected', command);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
valueChanged(parameterData: IUpdateInformation) {
|
valueChanged(parameterData: IUpdateInformation) {
|
||||||
this.$emit('change', parameterData);
|
this.$emit('change', parameterData);
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
:hint="hint"
|
:hint="hint"
|
||||||
:hide-issues="hideIssues"
|
:hide-issues="hideIssues"
|
||||||
:label="label"
|
:label="label"
|
||||||
|
:event-bus="eventBus"
|
||||||
@valueChanged="valueChanged"
|
@valueChanged="valueChanged"
|
||||||
@textInput="onTextInput"
|
@textInput="onTextInput"
|
||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
|
@ -98,6 +99,7 @@ import { useNDVStore } from '@/stores/ndv.store';
|
||||||
import { useSegment } from '@/stores/segment.store';
|
import { useSegment } from '@/stores/segment.store';
|
||||||
import { externalHooks } from '@/mixins/externalHooks';
|
import { externalHooks } from '@/mixins/externalHooks';
|
||||||
import { getMappedResult } from '@/utils/mappingUtils';
|
import { getMappedResult } from '@/utils/mappingUtils';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
type ParameterInputWrapperRef = InstanceType<typeof ParameterInputWrapper>;
|
type ParameterInputWrapperRef = InstanceType<typeof ParameterInputWrapper>;
|
||||||
|
|
||||||
|
@ -112,7 +114,10 @@ export default defineComponent({
|
||||||
ParameterInputWrapper,
|
ParameterInputWrapper,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
const eventBus = createEventBus();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
eventBus,
|
||||||
...useToast(),
|
...useToast(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -234,17 +239,14 @@ export default defineComponent({
|
||||||
this.menuExpanded = expanded;
|
this.menuExpanded = expanded;
|
||||||
},
|
},
|
||||||
optionSelected(command: string) {
|
optionSelected(command: string) {
|
||||||
const paramRef = this.$refs.param as ParameterInputWrapperRef | undefined;
|
this.eventBus.emit('optionSelected', command);
|
||||||
paramRef?.$emit('optionSelected', command);
|
|
||||||
},
|
},
|
||||||
valueChanged(parameterData: IUpdateInformation) {
|
valueChanged(parameterData: IUpdateInformation) {
|
||||||
this.$emit('valueChanged', parameterData);
|
this.$emit('valueChanged', parameterData);
|
||||||
},
|
},
|
||||||
onTextInput(parameterData: IUpdateInformation) {
|
onTextInput(parameterData: IUpdateInformation) {
|
||||||
const paramRef = this.$refs.param as ParameterInputWrapperRef | undefined;
|
|
||||||
|
|
||||||
if (isValueExpression(this.parameter, parameterData.value)) {
|
if (isValueExpression(this.parameter, parameterData.value)) {
|
||||||
paramRef?.$emit('optionSelected', 'addExpression');
|
this.eventBus.emit('optionSelected', 'addExpression');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDrop(newParamValue: string) {
|
onDrop(newParamValue: string) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
:expressionEvaluated="expressionValueComputed"
|
:expressionEvaluated="expressionValueComputed"
|
||||||
:label="label"
|
:label="label"
|
||||||
:data-test-id="`parameter-input-${parameter.name}`"
|
:data-test-id="`parameter-input-${parameter.name}`"
|
||||||
|
:event-bus="internalEventBus"
|
||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
@drop="onDrop"
|
@drop="onDrop"
|
||||||
|
@ -61,8 +62,8 @@ import type { INodeUi, IUpdateInformation, TargetItem } from '@/Interface';
|
||||||
import { workflowHelpers } from '@/mixins/workflowHelpers';
|
import { workflowHelpers } from '@/mixins/workflowHelpers';
|
||||||
import { isValueExpression } from '@/utils';
|
import { isValueExpression } from '@/utils';
|
||||||
import { useNDVStore } from '@/stores/ndv.store';
|
import { useNDVStore } from '@/stores/ndv.store';
|
||||||
|
import type { EventBus } from 'n8n-design-system/utils';
|
||||||
type ParamRef = InstanceType<typeof ParameterInput>;
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'parameter-input-wrapper',
|
name: 'parameter-input-wrapper',
|
||||||
|
@ -71,8 +72,16 @@ export default defineComponent({
|
||||||
ParameterInput,
|
ParameterInput,
|
||||||
InputHint,
|
InputHint,
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
internalEventBus: createEventBus(),
|
||||||
|
};
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$on('optionSelected', this.optionSelected);
|
this.eventBus.on('optionSelected', this.optionSelected);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.eventBus.off('optionSelected', this.optionSelected);
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
isReadOnly: {
|
isReadOnly: {
|
||||||
|
@ -124,6 +133,10 @@ export default defineComponent({
|
||||||
size: 'small',
|
size: 'small',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
eventBus: {
|
||||||
|
type: Object as PropType<EventBus>,
|
||||||
|
default: () => createEventBus(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useNDVStore),
|
...mapStores(useNDVStore),
|
||||||
|
@ -217,9 +230,7 @@ export default defineComponent({
|
||||||
this.$emit('drop', data);
|
this.$emit('drop', data);
|
||||||
},
|
},
|
||||||
optionSelected(command: string) {
|
optionSelected(command: string) {
|
||||||
const paramRef = this.$refs.param as ParamRef | undefined;
|
this.internalEventBus.emit('optionSelected', command);
|
||||||
|
|
||||||
paramRef?.$emit('optionSelected', command);
|
|
||||||
},
|
},
|
||||||
onValueChanged(parameterData: IUpdateInformation) {
|
onValueChanged(parameterData: IUpdateInformation) {
|
||||||
this.$emit('valueChanged', parameterData);
|
this.$emit('valueChanged', parameterData);
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
:hasMore="currentQueryHasMore"
|
:hasMore="currentQueryHasMore"
|
||||||
:errorView="currentQueryError"
|
:errorView="currentQueryError"
|
||||||
:width="width"
|
:width="width"
|
||||||
|
:event-bus="eventBus"
|
||||||
@input="onListItemSelected"
|
@input="onListItemSelected"
|
||||||
@hide="onDropdownHide"
|
@hide="onDropdownHide"
|
||||||
@filter="onSearchFilter"
|
@filter="onSearchFilter"
|
||||||
@loadMore="loadResourcesDebounced"
|
@loadMore="loadResourcesDebounced"
|
||||||
ref="dropdown"
|
|
||||||
>
|
>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div :class="$style.error" data-test-id="rlc-error-container">
|
<div :class="$style.error" data-test-id="rlc-error-container">
|
||||||
|
@ -176,8 +176,8 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||||
import { useNDVStore } from '@/stores/ndv.store';
|
import { useNDVStore } from '@/stores/ndv.store';
|
||||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
type ResourceLocatorDropdownRef = InstanceType<typeof ResourceLocatorDropdown>;
|
import type { EventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
interface IResourceLocatorQuery {
|
interface IResourceLocatorQuery {
|
||||||
results: INodeListSearchItems[];
|
results: INodeListSearchItems[];
|
||||||
|
@ -256,6 +256,10 @@ export default defineComponent({
|
||||||
loadOptionsMethod: {
|
loadOptionsMethod: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
eventBus: {
|
||||||
|
type: Object as PropType<EventBus>,
|
||||||
|
default: () => createEventBus(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -475,17 +479,20 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$on('refreshList', this.refreshList);
|
this.eventBus.on('refreshList', this.refreshList);
|
||||||
window.addEventListener('resize', this.setWidth);
|
window.addEventListener('resize', this.setWidth);
|
||||||
|
|
||||||
useNDVStore().$subscribe((mutation, state) => {
|
useNDVStore().$subscribe((mutation, state) => {
|
||||||
// Update the width when main panel dimension change
|
// Update the width when main panel dimension change
|
||||||
this.setWidth();
|
this.setWidth();
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setWidth();
|
this.setWidth();
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
this.eventBus.off('refreshList', this.refreshList);
|
||||||
window.removeEventListener('resize', this.setWidth);
|
window.removeEventListener('resize', this.setWidth);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -510,9 +517,8 @@ export default defineComponent({
|
||||||
this.trackEvent('User refreshed resource locator list');
|
this.trackEvent('User refreshed resource locator list');
|
||||||
},
|
},
|
||||||
onKeyDown(e: MouseEvent) {
|
onKeyDown(e: MouseEvent) {
|
||||||
const dropdownRef = this.$refs.dropdown as ResourceLocatorDropdownRef | undefined;
|
if (this.showResourceDropdown && !this.isSearchable) {
|
||||||
if (dropdownRef && this.showResourceDropdown && !this.isSearchable) {
|
this.eventBus.emit('keyDown', e);
|
||||||
dropdownRef.$emit('keyDown', e);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openResource(url: string) {
|
openResource(url: string) {
|
||||||
|
|
|
@ -82,6 +82,8 @@
|
||||||
import type { IResourceLocatorResultExpanded } from '@/Interface';
|
import type { IResourceLocatorResultExpanded } from '@/Interface';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
import type { EventBus } from 'n8n-design-system/utils';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
const SEARCH_BAR_HEIGHT_PX = 40;
|
const SEARCH_BAR_HEIGHT_PX = 40;
|
||||||
const SCROLL_MARGIN_PX = 10;
|
const SCROLL_MARGIN_PX = 10;
|
||||||
|
@ -120,6 +122,10 @@ export default defineComponent({
|
||||||
width: {
|
width: {
|
||||||
type: Number,
|
type: Number,
|
||||||
},
|
},
|
||||||
|
eventBus: {
|
||||||
|
type: Object as PropType<EventBus>,
|
||||||
|
default: () => createEventBus(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -128,7 +134,10 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$on('keyDown', this.onKeyDown);
|
this.eventBus.on('keyDown', this.onKeyDown);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.eventBus.off('keyDown', this.onKeyDown);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
sortedResources(): IResourceLocatorResultExpanded[] {
|
sortedResources(): IResourceLocatorResultExpanded[] {
|
||||||
|
|
|
@ -1,11 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="__html-display ph-no-capture" v-html="html"></div>
|
<iframe class="__html-display ph-no-capture" :srcdoc="html" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
import sanitizeHtml, { defaults, type IOptions as SanitizeOptions } from 'sanitize-html';
|
||||||
import type { INodeExecutionData } from 'n8n-workflow';
|
import type { INodeExecutionData } from 'n8n-workflow';
|
||||||
|
|
||||||
|
const sanitizeOptions: SanitizeOptions = {
|
||||||
|
allowVulnerableTags: false,
|
||||||
|
enforceHtmlBoundary: false,
|
||||||
|
disallowedTagsMode: 'discard',
|
||||||
|
allowedTags: [...defaults.allowedTags, 'style', 'img', 'title'],
|
||||||
|
allowedAttributes: {
|
||||||
|
...defaults.allowedAttributes,
|
||||||
|
'*': ['class', 'style'],
|
||||||
|
},
|
||||||
|
transformTags: {
|
||||||
|
head: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RunDataHtml',
|
name: 'RunDataHtml',
|
||||||
props: {
|
props: {
|
||||||
|
@ -15,29 +30,8 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
html() {
|
html() {
|
||||||
if (!this.inputData) return '';
|
const markup = (this.inputData?.[0].json.html as string) ?? '';
|
||||||
|
return sanitizeHtml(markup, sanitizeOptions);
|
||||||
return this.scopeCss(this.inputData[0].json.html as string);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* Scope all CSS selectors to prevent user stylesheets from leaking.
|
|
||||||
*/
|
|
||||||
scopeCss(str: string) {
|
|
||||||
const stylesheets = str.match(/<style>([\s\S]*?)<\/style>/g);
|
|
||||||
|
|
||||||
if (!stylesheets) return str;
|
|
||||||
|
|
||||||
const map = stylesheets.reduce<Record<string, string>>((acc, match) => {
|
|
||||||
match.split('\n').forEach((line) => {
|
|
||||||
if (line.endsWith('{')) acc[line] = ['.__html-display', line].join(' ');
|
|
||||||
});
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
return Object.entries(map).reduce((acc, [key, value]) => acc.replace(key, value), str);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -45,6 +39,7 @@ export default {
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.__html-display {
|
.__html-display {
|
||||||
padding: 0 var(--spacing-s);
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
@observed="onObserved"
|
@observed="onObserved"
|
||||||
class="tags-container"
|
class="tags-container"
|
||||||
:enabled="responsive"
|
:enabled="responsive"
|
||||||
|
:event-bus="intersectionEventBus"
|
||||||
>
|
>
|
||||||
<template>
|
<template>
|
||||||
<span class="tags">
|
<span class="tags">
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
:class="{ hidden: tag.hidden }"
|
:class="{ hidden: tag.hidden }"
|
||||||
:data-id="tag.id"
|
:data-id="tag.id"
|
||||||
:enabled="responsive"
|
:enabled="responsive"
|
||||||
|
:event-bus="intersectionEventBus"
|
||||||
v-else
|
v-else
|
||||||
>
|
>
|
||||||
<el-tag :title="tag.name" type="info" size="small" :class="{ hoverable }">
|
<el-tag :title="tag.name" type="info" size="small" :class="{ hoverable }">
|
||||||
|
@ -46,6 +48,7 @@ import IntersectionObserver from './IntersectionObserver.vue';
|
||||||
import IntersectionObserved from './IntersectionObserved.vue';
|
import IntersectionObserved from './IntersectionObserved.vue';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTagsStore } from '@/stores/tags.store';
|
import { useTagsStore } from '@/stores/tags.store';
|
||||||
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
|
|
||||||
// random upper limit if none is set to minimize performance impact of observers
|
// random upper limit if none is set to minimize performance impact of observers
|
||||||
const DEFAULT_MAX_TAGS_LIMIT = 20;
|
const DEFAULT_MAX_TAGS_LIMIT = 20;
|
||||||
|
@ -62,6 +65,7 @@ export default defineComponent({
|
||||||
props: ['tagIds', 'limit', 'clickable', 'responsive', 'hoverable'],
|
props: ['tagIds', 'limit', 'clickable', 'responsive', 'hoverable'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
intersectionEventBus: createEventBus(),
|
||||||
visibility: {} as { [id: string]: boolean },
|
visibility: {} as { [id: string]: boolean },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
* unsafe onclick attribute
|
* unsafe onclick attribute
|
||||||
*/
|
*/
|
||||||
import { reactive, del, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue';
|
import { reactive, del, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue';
|
||||||
|
import { globalLinkActionsEventBus } from '@/event-bus';
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
customActions: {} as Record<string, Function>,
|
customActions: {} as Record<string, Function>,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
function registerCustomAction(key: string, action: Function) {
|
function registerCustomAction({ key, action }: { key: string; action: Function }) {
|
||||||
state.customActions[key] = action;
|
state.customActions[key] = action;
|
||||||
}
|
}
|
||||||
function unregisterCustomAction(key: string) {
|
function unregisterCustomAction(key: string) {
|
||||||
|
@ -42,13 +43,15 @@ export default () => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
window.addEventListener('click', delegateClick);
|
window.addEventListener('click', delegateClick);
|
||||||
instance?.proxy.$root.$on('registerGlobalLinkAction', registerCustomAction);
|
|
||||||
|
globalLinkActionsEventBus.on('registerGlobalLinkAction', registerCustomAction);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
window.removeEventListener('click', delegateClick);
|
window.removeEventListener('click', delegateClick);
|
||||||
instance?.proxy.$root.$off('registerGlobalLinkAction', registerCustomAction);
|
|
||||||
|
globalLinkActionsEventBus.off('registerGlobalLinkAction', registerCustomAction);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export * from './code-node-editor';
|
export * from './code-node-editor';
|
||||||
export * from './data-pinning';
|
export * from './data-pinning';
|
||||||
|
export * from './link-actions';
|
||||||
export * from './html-editor';
|
export * from './html-editor';
|
||||||
export * from './node-view';
|
export * from './node-view';
|
||||||
|
|
3
packages/editor-ui/src/event-bus/link-actions.ts
Normal file
3
packages/editor-ui/src/event-bus/link-actions.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { createEventBus } from 'n8n-design-system';
|
||||||
|
|
||||||
|
export const globalLinkActionsEventBus = createEventBus();
|
|
@ -1,50 +0,0 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
function broadcast(
|
|
||||||
this: InstanceType<typeof EmitterMixin>,
|
|
||||||
componentName: string,
|
|
||||||
eventName: string,
|
|
||||||
params: any,
|
|
||||||
) {
|
|
||||||
this.$children.forEach((child) => {
|
|
||||||
const name = child.$options.name;
|
|
||||||
|
|
||||||
if (name === componentName) {
|
|
||||||
// eslint-disable-next-line prefer-spread
|
|
||||||
child.$emit.apply(child, [eventName].concat(params) as Parameters<typeof child.$emit>);
|
|
||||||
} else {
|
|
||||||
broadcast.apply(
|
|
||||||
child as InstanceType<typeof EmitterMixin>,
|
|
||||||
[componentName, eventName].concat([params]) as Parameters<typeof broadcast>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const EmitterMixin = defineComponent({
|
|
||||||
methods: {
|
|
||||||
$dispatch(componentName: string, eventName: string, params: any) {
|
|
||||||
let parent = this.$parent || this.$root;
|
|
||||||
let name = parent.$options.name;
|
|
||||||
|
|
||||||
while (parent && (!name || name !== componentName)) {
|
|
||||||
parent = parent.$parent as InstanceType<typeof EmitterMixin>;
|
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
name = parent.$options.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (parent) {
|
|
||||||
// eslint-disable-next-line prefer-spread
|
|
||||||
parent.$emit.apply(parent, [eventName].concat(params) as Parameters<typeof parent.$emit>);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
$broadcast(componentName: string, eventName: string, params: any) {
|
|
||||||
broadcast.call(this, componentName, eventName, params);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default EmitterMixin;
|
|
|
@ -24,7 +24,7 @@ import { TelemetryHelpers } from 'n8n-workflow';
|
||||||
|
|
||||||
import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
|
import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
|
||||||
import { getTriggerNodeServiceName } from '@/utils';
|
import { getTriggerNodeServiceName } from '@/utils';
|
||||||
import { codeNodeEditorEventBus } from '@/event-bus';
|
import { codeNodeEditorEventBus, globalLinkActionsEventBus } from '@/event-bus';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
|
@ -351,9 +351,12 @@ export const pushConnection = defineComponent({
|
||||||
|
|
||||||
let action;
|
let action;
|
||||||
if (!isSavingExecutions) {
|
if (!isSavingExecutions) {
|
||||||
this.$root.$emit('registerGlobalLinkAction', 'open-settings', async () => {
|
globalLinkActionsEventBus.emit('registerGlobalLinkAction', {
|
||||||
if (this.workflowsStore.isNewWorkflow) await this.saveAsNewWorkflow();
|
key: 'open-settings',
|
||||||
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
action: async () => {
|
||||||
|
if (this.workflowsStore.isNewWorkflow) await this.saveAsNewWorkflow();
|
||||||
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
action =
|
action =
|
||||||
|
|
|
@ -1231,8 +1231,6 @@
|
||||||
"settings.users.setupMyAccount": "Set up my owner account",
|
"settings.users.setupMyAccount": "Set up my owner account",
|
||||||
"settings.users.setupToInviteUsers": "To invite users, set up your own account",
|
"settings.users.setupToInviteUsers": "To invite users, set up your own account",
|
||||||
"settings.users.setupToInviteUsersInfo": "Invited users won’t be able to see workflows and credentials of other users unless you upgrade. <a href=\"https://docs.n8n.io/user-management/\" target=\"_blank\">More info</a> <br /> <br />",
|
"settings.users.setupToInviteUsersInfo": "Invited users won’t be able to see workflows and credentials of other users unless you upgrade. <a href=\"https://docs.n8n.io/user-management/\" target=\"_blank\">More info</a> <br /> <br />",
|
||||||
"settings.users.setupSMTPInfo": "You will need details of an {link} to complete the setup.",
|
|
||||||
"settings.users.setupSMTPInfo.link": "SMTP server",
|
|
||||||
"settings.users.smtpToAddUsersWarning": "Set up SMTP before adding users (so that n8n can send them invitation emails). <a target=\"_blank\" href=\"https://docs.n8n.io/hosting/authentication/user-management-self-hosted/\">Instructions</a>",
|
"settings.users.smtpToAddUsersWarning": "Set up SMTP before adding users (so that n8n can send them invitation emails). <a target=\"_blank\" href=\"https://docs.n8n.io/hosting/authentication/user-management-self-hosted/\">Instructions</a>",
|
||||||
"settings.users.transferWorkflowsAndCredentials": "Transfer their workflows and credentials to another user",
|
"settings.users.transferWorkflowsAndCredentials": "Transfer their workflows and credentials to another user",
|
||||||
"settings.users.transferredToUser": "Data transferred to {user}",
|
"settings.users.transferredToUser": "Data transferred to {user}",
|
||||||
|
|
|
@ -672,9 +672,12 @@ export default defineComponent({
|
||||||
? this.$locale.baseText('nodeView.addOrEnableTriggerNode')
|
? this.$locale.baseText('nodeView.addOrEnableTriggerNode')
|
||||||
: this.$locale.baseText('nodeView.addATriggerNodeFirst');
|
: this.$locale.baseText('nodeView.addATriggerNodeFirst');
|
||||||
|
|
||||||
this.registerCustomAction('showNodeCreator', () =>
|
this.registerCustomAction({
|
||||||
this.showTriggerCreator(NODE_CREATOR_OPEN_SOURCES.NO_TRIGGER_EXECUTION_TOOLTIP),
|
key: 'showNodeCreator',
|
||||||
);
|
action: () =>
|
||||||
|
this.showTriggerCreator(NODE_CREATOR_OPEN_SOURCES.NO_TRIGGER_EXECUTION_TOOLTIP),
|
||||||
|
});
|
||||||
|
|
||||||
const notice = this.showMessage({
|
const notice = this.showMessage({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
title: this.$locale.baseText('nodeView.cantExecuteNoTrigger'),
|
title: this.$locale.baseText('nodeView.cantExecuteNoTrigger'),
|
||||||
|
@ -1050,7 +1053,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$router.currentRoute.name === VIEWS.NEW_WORKFLOW) {
|
if (this.$router.currentRoute.name === VIEWS.NEW_WORKFLOW) {
|
||||||
this.$root.$emit('newWorkflow');
|
nodeViewEventBus.emit('newWorkflow');
|
||||||
} else {
|
} else {
|
||||||
void this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
void this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
||||||
}
|
}
|
||||||
|
@ -3913,9 +3916,9 @@ export default defineComponent({
|
||||||
window.addEventListener('message', this.onPostMessageReceived);
|
window.addEventListener('message', this.onPostMessageReceived);
|
||||||
window.addEventListener('pageshow', this.onPageShow);
|
window.addEventListener('pageshow', this.onPageShow);
|
||||||
|
|
||||||
this.$root.$on('newWorkflow', this.newWorkflow);
|
nodeViewEventBus.on('newWorkflow', this.newWorkflow);
|
||||||
this.$root.$on('importWorkflowData', this.onImportWorkflowDataEvent);
|
nodeViewEventBus.on('importWorkflowData', this.onImportWorkflowDataEvent);
|
||||||
this.$root.$on('importWorkflowUrl', this.onImportWorkflowUrlEvent);
|
nodeViewEventBus.on('importWorkflowUrl', this.onImportWorkflowUrlEvent);
|
||||||
historyBus.on('nodeMove', this.onMoveNode);
|
historyBus.on('nodeMove', this.onMoveNode);
|
||||||
historyBus.on('revertAddNode', this.onRevertAddNode);
|
historyBus.on('revertAddNode', this.onRevertAddNode);
|
||||||
historyBus.on('revertRemoveNode', this.onRevertRemoveNode);
|
historyBus.on('revertRemoveNode', this.onRevertRemoveNode);
|
||||||
|
@ -3938,9 +3941,9 @@ export default defineComponent({
|
||||||
window.removeEventListener('beforeunload', this.onBeforeUnload);
|
window.removeEventListener('beforeunload', this.onBeforeUnload);
|
||||||
window.removeEventListener('pageshow', this.onPageShow);
|
window.removeEventListener('pageshow', this.onPageShow);
|
||||||
|
|
||||||
this.$root.$off('newWorkflow', this.newWorkflow);
|
nodeViewEventBus.off('newWorkflow', this.newWorkflow);
|
||||||
this.$root.$off('importWorkflowData', this.onImportWorkflowDataEvent);
|
nodeViewEventBus.off('importWorkflowData', this.onImportWorkflowDataEvent);
|
||||||
this.$root.$off('importWorkflowUrl', this.onImportWorkflowUrlEvent);
|
nodeViewEventBus.off('importWorkflowUrl', this.onImportWorkflowUrlEvent);
|
||||||
historyBus.off('nodeMove', this.onMoveNode);
|
historyBus.off('nodeMove', this.onMoveNode);
|
||||||
historyBus.off('revertAddNode', this.onRevertAddNode);
|
historyBus.off('revertAddNode', this.onRevertAddNode);
|
||||||
historyBus.off('revertRemoveNode', this.onRevertRemoveNode);
|
historyBus.off('revertRemoveNode', this.onRevertRemoveNode);
|
||||||
|
@ -3959,9 +3962,9 @@ export default defineComponent({
|
||||||
this.instance.destroy();
|
this.instance.destroy();
|
||||||
this.uiStore.stateIsDirty = false;
|
this.uiStore.stateIsDirty = false;
|
||||||
window.removeEventListener('message', this.onPostMessageReceived);
|
window.removeEventListener('message', this.onPostMessageReceived);
|
||||||
this.$root.$off('newWorkflow', this.newWorkflow);
|
nodeViewEventBus.off('newWorkflow', this.newWorkflow);
|
||||||
this.$root.$off('importWorkflowData', this.onImportWorkflowDataEvent);
|
nodeViewEventBus.off('importWorkflowData', this.onImportWorkflowDataEvent);
|
||||||
this.$root.$off('importWorkflowUrl', this.onImportWorkflowUrlEvent);
|
nodeViewEventBus.off('importWorkflowUrl', this.onImportWorkflowUrlEvent);
|
||||||
this.workflowsStore.setWorkflowId(PLACEHOLDER_EMPTY_WORKFLOW_ID);
|
this.workflowsStore.setWorkflowId(PLACEHOLDER_EMPTY_WORKFLOW_ID);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -117,7 +117,7 @@ const repoUrlValidationRules: Array<Rule | RuleGroup> = [
|
||||||
{
|
{
|
||||||
name: 'MATCH_REGEX',
|
name: 'MATCH_REGEX',
|
||||||
config: {
|
config: {
|
||||||
regex: /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\.git)(\/?|\#[-\d\w._]+?)$/,
|
regex: /^(?!https?:\/\/)(?:git|ssh|git@[-\w.]+):(\/\/)?(.*?)(\.git)(\/?|\#[-\d\w._]+?)$/,
|
||||||
message: locale.baseText('settings.versionControl.repoUrlInvalid'),
|
message: locale.baseText('settings.versionControl.repoUrlInvalid'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,8 +2,8 @@ import type { IDataObject, IExecuteFunctions, ILoadOptionsFunctions } from 'n8n-
|
||||||
|
|
||||||
import type { OptionsWithUri } from 'request';
|
import type { OptionsWithUri } from 'request';
|
||||||
|
|
||||||
import flow from 'lodash.flow';
|
import flow from 'lodash/flow';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AllFieldsUi,
|
AllFieldsUi,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type {
|
||||||
INodePropertyOptions,
|
INodePropertyOptions,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make an API request to Asana
|
* Make an API request to Asana
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { jsonParse, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { awsApiRequestSOAP } from './GenericFunctions';
|
import { awsApiRequestSOAP } from './GenericFunctions';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
export class AwsSnsTrigger implements INodeType {
|
export class AwsSnsTrigger implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import { parseString } from 'xml2js';
|
import { parseString } from 'xml2js';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import { parseString } from 'xml2js';
|
import { parseString } from 'xml2js';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import { parseString } from 'xml2js';
|
import { parseString } from 'xml2js';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import { parseString } from 'xml2js';
|
import { parseString } from 'xml2js';
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
export async function awsApiRequest(
|
export async function awsApiRequest(
|
||||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions,
|
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions,
|
||||||
|
|
|
@ -16,7 +16,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
function getEndpointForService(
|
function getEndpointForService(
|
||||||
service: string,
|
service: string,
|
||||||
|
|
|
@ -32,8 +32,8 @@ import type {
|
||||||
} from './descriptions/MemberDescription';
|
} from './descriptions/MemberDescription';
|
||||||
import { memberFields, memberOperations } from './descriptions/MemberDescription';
|
import { memberFields, memberOperations } from './descriptions/MemberDescription';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import partialRight from 'lodash.partialright';
|
import partialRight from 'lodash/partialRight';
|
||||||
|
|
||||||
export class Bitwarden implements INodeType {
|
export class Bitwarden implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
import upperFirst from 'lodash.upperfirst';
|
import upperFirst from 'lodash/upperFirst';
|
||||||
|
|
||||||
import { createHash } from 'crypto';
|
import { createHash } from 'crypto';
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import type { IDataObject, INodeExecutionData } from 'n8n-workflow';
|
import type { IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||||
|
|
||||||
import difference from 'lodash.difference';
|
import difference from 'lodash/difference';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import intersection from 'lodash.intersection';
|
import intersection from 'lodash/intersection';
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
import unset from 'lodash.unset';
|
import unset from 'lodash/unset';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import union from 'lodash.union';
|
import union from 'lodash/union';
|
||||||
import { fuzzyCompare } from '../../utils/utilities';
|
import { fuzzyCompare } from '../../utils/utilities';
|
||||||
|
|
||||||
type PairToMatch = {
|
type PairToMatch = {
|
||||||
|
|
|
@ -14,8 +14,8 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
import flow from 'lodash.flow';
|
import flow from 'lodash/flow';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AddressFixedCollection,
|
AddressFixedCollection,
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { responderFields, respondersOperations } from './ResponderDescription';
|
||||||
|
|
||||||
import { jobFields, jobOperations } from './JobDescription';
|
import { jobFields, jobOperations } from './JobDescription';
|
||||||
|
|
||||||
import upperFirst from 'lodash.upperfirst';
|
import upperFirst from 'lodash/upperFirst';
|
||||||
|
|
||||||
import type { IJob } from './AnalyzerInterface';
|
import type { IJob } from './AnalyzerInterface';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
IExecuteFunctions,
|
IExecuteFunctions,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import type {
|
||||||
IHttpRequestOptions,
|
IHttpRequestOptions,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
export async function customerIoApiRequest(
|
export async function customerIoApiRequest(
|
||||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import type {
|
||||||
|
|
||||||
import { deepCopy, NodeOperationError } from 'n8n-workflow';
|
import { deepCopy, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
|
|
||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
|
|
||||||
|
|
10
packages/nodes-base/nodes/DebugHelper/DebugHelper.node.json
Normal file
10
packages/nodes-base/nodes/DebugHelper/DebugHelper.node.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"node": "n8n-nodes-base.debughelper",
|
||||||
|
"nodeVersion": "1.0",
|
||||||
|
"codexVersion": "1.0",
|
||||||
|
"categories": ["Development"],
|
||||||
|
"resources": {
|
||||||
|
"credentialDocumentation": [],
|
||||||
|
"primaryDocumentation": []
|
||||||
|
}
|
||||||
|
}
|
374
packages/nodes-base/nodes/DebugHelper/DebugHelper.node.ts
Normal file
374
packages/nodes-base/nodes/DebugHelper/DebugHelper.node.ts
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
import type {
|
||||||
|
IExecuteFunctions,
|
||||||
|
INodeExecutionData,
|
||||||
|
INodeType,
|
||||||
|
INodeTypeDescription,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||||
|
import {
|
||||||
|
generateCreditCard,
|
||||||
|
generateIPv4,
|
||||||
|
generateIPv6,
|
||||||
|
generateLocation,
|
||||||
|
generateMAC,
|
||||||
|
generateNanoid,
|
||||||
|
generateRandomAddress,
|
||||||
|
generateRandomEmail,
|
||||||
|
generateRandomUser,
|
||||||
|
generateURL,
|
||||||
|
generateUUID,
|
||||||
|
generateVersion,
|
||||||
|
} from './randomData';
|
||||||
|
import { setSeed, array as mfArray } from 'minifaker';
|
||||||
|
import { generateGarbageMemory, runGarbageCollector } from './functions';
|
||||||
|
|
||||||
|
export class DebugHelper implements INodeType {
|
||||||
|
description: INodeTypeDescription = {
|
||||||
|
displayName: 'DebugHelper',
|
||||||
|
name: 'debugHelper',
|
||||||
|
icon: 'file:DebugHelper.svg',
|
||||||
|
group: ['output'],
|
||||||
|
subtitle: '={{$parameter["category"]}}',
|
||||||
|
description: 'Causes problems intentionally and generates useful data for debugging',
|
||||||
|
version: 1,
|
||||||
|
defaults: {
|
||||||
|
name: 'DebugHelper',
|
||||||
|
},
|
||||||
|
inputs: ['main'],
|
||||||
|
outputs: ['main'],
|
||||||
|
credentials: [],
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Category',
|
||||||
|
name: 'category',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Do Nothing',
|
||||||
|
value: 'doNothing',
|
||||||
|
description: 'Does nothing',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Throw Error',
|
||||||
|
value: 'throwError',
|
||||||
|
description: 'Throws an error with the specified type and message',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Out Of Memory',
|
||||||
|
value: 'oom',
|
||||||
|
description: 'Generates a large amount of memory to cause an out of memory error',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Generate Random Data',
|
||||||
|
value: 'randomData',
|
||||||
|
description: 'Generates random data sets',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'throwError',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Error Type',
|
||||||
|
name: 'throwErrorType',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'NodeApiError',
|
||||||
|
value: 'NodeApiError',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NodeOperationError',
|
||||||
|
value: 'NodeOperationError',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Error',
|
||||||
|
value: 'Error',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'NodeApiError',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['throwError'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Error Message',
|
||||||
|
name: 'throwErrorMessage',
|
||||||
|
type: 'string',
|
||||||
|
default: 'Node has thrown an error',
|
||||||
|
description: 'The message to send as part of the error',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['throwError'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Memory Size to Generate',
|
||||||
|
name: 'memorySizeValue',
|
||||||
|
type: 'number',
|
||||||
|
default: 10,
|
||||||
|
description: 'The approximate amount of memory to generate. Be generous...',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['oom'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Data Type',
|
||||||
|
name: 'randomDataType',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Address',
|
||||||
|
value: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Coordinates',
|
||||||
|
value: 'latLong',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Credit Card',
|
||||||
|
value: 'creditCard',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Email',
|
||||||
|
value: 'email',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'IPv4',
|
||||||
|
value: 'ipv4',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'IPv6',
|
||||||
|
value: 'ipv6',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'MAC',
|
||||||
|
value: 'macAddress',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NanoIds',
|
||||||
|
value: 'nanoid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'URL',
|
||||||
|
value: 'url',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'User Data',
|
||||||
|
value: 'user',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'UUID',
|
||||||
|
value: 'uuid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Version',
|
||||||
|
value: 'semver',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'user',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['randomData'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'NanoId Alphabet',
|
||||||
|
name: 'nanoidAlphabet',
|
||||||
|
type: 'string',
|
||||||
|
default: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||||
|
description: 'The alphabet to use for generating the nanoIds',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['randomData'],
|
||||||
|
randomDataType: ['nanoid'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'NanoId Length',
|
||||||
|
name: 'nanoidLength',
|
||||||
|
type: 'string',
|
||||||
|
default: '16',
|
||||||
|
description: 'The length of each nanoIds',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['randomData'],
|
||||||
|
randomDataType: ['nanoid'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Seed',
|
||||||
|
name: 'randomDataSeed',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: 'Leave empty for random seed',
|
||||||
|
description:
|
||||||
|
'If set, seed to use for generating the data (same seed will generate the same data)',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['randomData'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Number of Items to Generate',
|
||||||
|
name: 'randomDataCount',
|
||||||
|
type: 'number',
|
||||||
|
default: 10,
|
||||||
|
description: 'The number of random data items to generate into an array',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['randomData'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Output as Single Array',
|
||||||
|
name: 'randomDataSingleArray',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Whether to output a single array instead of multiple items',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
category: ['randomData'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
|
const items = this.getInputData();
|
||||||
|
const returnData: INodeExecutionData[] = [];
|
||||||
|
const category = this.getNodeParameter('category', 0) as string;
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
try {
|
||||||
|
switch (category) {
|
||||||
|
case 'doNothing':
|
||||||
|
// as it says on the tin...
|
||||||
|
break;
|
||||||
|
case 'throwError':
|
||||||
|
const throwErrorType = this.getNodeParameter('throwErrorType', 0) as string;
|
||||||
|
const throwErrorMessage = this.getNodeParameter('throwErrorMessage', 0) as string;
|
||||||
|
switch (throwErrorType) {
|
||||||
|
case 'NodeApiError':
|
||||||
|
throw new NodeApiError(
|
||||||
|
this.getNode(),
|
||||||
|
{ message: throwErrorMessage },
|
||||||
|
{ message: throwErrorMessage },
|
||||||
|
);
|
||||||
|
case 'NodeOperationError':
|
||||||
|
throw new NodeOperationError(this.getNode(), throwErrorMessage, {
|
||||||
|
message: throwErrorMessage,
|
||||||
|
});
|
||||||
|
case 'Error':
|
||||||
|
// eslint-disable-next-line n8n-nodes-base/node-execute-block-wrong-error-thrown
|
||||||
|
throw new Error(throwErrorMessage);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'oom':
|
||||||
|
const memorySizeValue = this.getNodeParameter('memorySizeValue', 0) as number;
|
||||||
|
runGarbageCollector();
|
||||||
|
const memUsed = generateGarbageMemory(memorySizeValue);
|
||||||
|
items[i].json = memUsed;
|
||||||
|
returnData.push(items[i]);
|
||||||
|
break;
|
||||||
|
case 'randomData':
|
||||||
|
const randomDataType = this.getNodeParameter('randomDataType', 0) as string;
|
||||||
|
const randomDataCount = this.getNodeParameter('randomDataCount', 0) as number;
|
||||||
|
const randomDataSeed = this.getNodeParameter('randomDataSeed', 0) as string;
|
||||||
|
const randomDataSingleArray = this.getNodeParameter(
|
||||||
|
'randomDataSingleArray',
|
||||||
|
0,
|
||||||
|
) as boolean;
|
||||||
|
const newItem: INodeExecutionData = {
|
||||||
|
json: {},
|
||||||
|
pairedItem: { item: i },
|
||||||
|
};
|
||||||
|
if (randomDataSeed !== '') {
|
||||||
|
setSeed(randomDataSeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
let randomFn: () => any = generateRandomUser;
|
||||||
|
switch (randomDataType) {
|
||||||
|
case 'user':
|
||||||
|
randomFn = generateRandomUser;
|
||||||
|
break;
|
||||||
|
case 'email':
|
||||||
|
randomFn = generateRandomEmail;
|
||||||
|
break;
|
||||||
|
case 'address':
|
||||||
|
randomFn = generateRandomAddress;
|
||||||
|
break;
|
||||||
|
case 'creditCard':
|
||||||
|
randomFn = generateCreditCard;
|
||||||
|
break;
|
||||||
|
case 'uuid':
|
||||||
|
randomFn = generateUUID;
|
||||||
|
break;
|
||||||
|
case 'macAddress':
|
||||||
|
randomFn = generateMAC;
|
||||||
|
break;
|
||||||
|
case 'ipv4':
|
||||||
|
randomFn = generateIPv4;
|
||||||
|
break;
|
||||||
|
case 'ipv6':
|
||||||
|
randomFn = generateIPv6;
|
||||||
|
break;
|
||||||
|
case 'latLong':
|
||||||
|
randomFn = generateLocation;
|
||||||
|
break;
|
||||||
|
case 'semver':
|
||||||
|
randomFn = generateVersion;
|
||||||
|
break;
|
||||||
|
case 'url':
|
||||||
|
randomFn = generateURL;
|
||||||
|
break;
|
||||||
|
case 'nanoid':
|
||||||
|
const nanoidAlphabet = this.getNodeParameter('nanoidAlphabet', 0) as string;
|
||||||
|
const nanoidLength = this.getNodeParameter('nanoidLength', 0) as string;
|
||||||
|
randomFn = () => generateNanoid(nanoidAlphabet, nanoidLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const generatedItems = mfArray(randomDataCount, randomFn);
|
||||||
|
if (randomDataSingleArray) {
|
||||||
|
newItem.json = { generatedItems };
|
||||||
|
returnData.push(newItem);
|
||||||
|
} else {
|
||||||
|
for (const generatedItem of generatedItems) {
|
||||||
|
returnData.push({
|
||||||
|
json: generatedItem,
|
||||||
|
pairedItem: { item: i },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (this.continueOnFail()) {
|
||||||
|
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||||
|
this.helpers.returnJsonArray({ error: error.message }),
|
||||||
|
{ itemData: { item: i } },
|
||||||
|
);
|
||||||
|
returnData.push(...executionErrorData);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.prepareOutputData(returnData);
|
||||||
|
}
|
||||||
|
}
|
28
packages/nodes-base/nodes/DebugHelper/DebugHelper.svg
Normal file
28
packages/nodes-base/nodes/DebugHelper/DebugHelper.svg
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg height="800px" width="800px" version="1.1" id="Layer_1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve">
|
||||||
|
<path style="fill:#F4A026;" d="M345,167c32.953,0,46.333,40.047,46.333,73v100.333c0,74.375-60.292,134.667-134.667,134.667l0,0
|
||||||
|
C182.292,475,122,414.708,122,340.333V240c0-32.953,13.38-73,46.333-73H345z"/>
|
||||||
|
<path style="fill:#CA463D;" d="M309,200.333H204.333C185.372,200.333,170,184.961,170,166l0,0c0-39.948,32.385-72.333,72.333-72.333
|
||||||
|
H271c39.948,0,72.333,32.385,72.333,72.333l0,0C343.333,184.961,327.961,200.333,309,200.333z"/>
|
||||||
|
<path d="M498.667,290.667H404V240c0-1.016,0.313-2.036,0.291-3.055C452.4,231.927,480,200.272,480,148.333v-12
|
||||||
|
c0-7.364-5.971-13.333-13.333-13.333s-13.333,5.969-13.333,13.333v12c0,38.399-17.005,58.821-51.885,62.167
|
||||||
|
c-6.069-27.025-20.875-50.381-45.537-55.7c-3.745-28.54-21.413-52.689-46.115-65.227c10.321-10.501,16.871-24.887,16.871-40.74V37
|
||||||
|
c0-7.364-5.971-13.333-13.333-13.333S300,29.636,300,37v11.833C300,66.203,285.536,80,268.167,80h-23
|
||||||
|
c-17.369,0-31.833-13.797-31.833-31.167V37c0-7.364-5.971-13.333-13.333-13.333S186.667,29.636,186.667,37v11.833
|
||||||
|
c0,15.853,6.549,30.239,16.871,40.741c-24.701,12.537-42.453,36.687-46.199,65.227c-24.695,5.324-39.465,28.736-45.519,55.808
|
||||||
|
c-35.759-2.96-53.153-23.403-53.153-62.276v-12c0-7.364-5.971-13.333-13.333-13.333S32,128.969,32,136.333v12
|
||||||
|
c0,52.415,27.439,84.168,76.375,88.739C108.353,238.048,108,239.025,108,240v50.667H13.333C5.971,290.667,0,296.636,0,304
|
||||||
|
c0,7.364,5.971,13.333,13.333,13.333H108v23c0,10.628,1.469,20.993,3.608,30.992C60.659,374.777,32,406.773,32,460.333v12
|
||||||
|
c0,7.364,5.971,13.333,13.333,13.333s13.333-5.969,13.333-13.333v-12c0-41.795,20.151-62.291,61.565-62.649
|
||||||
|
c22.451,53.208,75.151,90.649,136.435,90.649c61.276,0,113.971-37.432,136.425-90.629c40.519,0.784,60.241,21.283,60.241,62.629v12
|
||||||
|
c0,7.364,5.971,13.333,13.333,13.333S480,479.697,480,472.333v-12c0-53.1-28.823-85.013-78.96-88.921
|
||||||
|
c2.151-10.025,2.96-20.421,2.96-31.079v-23h94.667c7.363,0,13.333-5.969,13.333-13.333C512,296.636,506.029,290.667,498.667,290.667
|
||||||
|
z M242.333,106.667h2.833h23H271c32.532,0,59,26.468,59,59c0,11.58-9.42,21-21,21H204.333c-11.58,0-21-9.42-21-21
|
||||||
|
C183.333,133.135,209.801,106.667,242.333,106.667z M134.667,340.333V240c0-20.793,6.948-50.531,24.483-58.035
|
||||||
|
c6.627,18.368,24.56,31.368,45.184,31.368h38.333v247.521C182.333,453.891,134.667,402.501,134.667,340.333z M269.333,461.007
|
||||||
|
V213.333H309c20.624,0,37.891-13,44.517-31.368c17.535,7.504,23.816,37.241,23.816,58.035v100.333
|
||||||
|
C377.333,402.96,330.307,454.653,269.333,461.007z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
30
packages/nodes-base/nodes/DebugHelper/functions.ts
Normal file
30
packages/nodes-base/nodes/DebugHelper/functions.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { setFlagsFromString } from 'v8';
|
||||||
|
import { runInNewContext } from 'vm';
|
||||||
|
|
||||||
|
export const runGarbageCollector = () => {
|
||||||
|
try {
|
||||||
|
setFlagsFromString('--expose_gc');
|
||||||
|
const gc = runInNewContext('gc'); // nocommit
|
||||||
|
gc();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateGarbageMemory = (sizeInMB: number, onHeap = true) => {
|
||||||
|
const divider = onHeap ? 8 : 1;
|
||||||
|
const size = Math.max(1, Math.floor((sizeInMB * 1024 * 1024) / divider));
|
||||||
|
if (onHeap) {
|
||||||
|
// arrays are allocated on the heap
|
||||||
|
// size in this case is only an approximation...
|
||||||
|
const array = Array(size);
|
||||||
|
array.fill(0);
|
||||||
|
} else {
|
||||||
|
const array = new Uint8Array(size);
|
||||||
|
array.fill(0);
|
||||||
|
}
|
||||||
|
// const used = process.memoryUsage().heapUsed / 1024 / 1024;
|
||||||
|
// const external = process.memoryUsage().external / 1024 / 1024;
|
||||||
|
// console.log(`heap: ${used} MB / external: ${external} MB`);
|
||||||
|
return { ...process.memoryUsage() };
|
||||||
|
};
|
101
packages/nodes-base/nodes/DebugHelper/randomData.ts
Normal file
101
packages/nodes-base/nodes/DebugHelper/randomData.ts
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import {
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
streetAddress,
|
||||||
|
cityName,
|
||||||
|
zipCode,
|
||||||
|
state,
|
||||||
|
country,
|
||||||
|
password,
|
||||||
|
creditCardNumber,
|
||||||
|
creditCardCVV,
|
||||||
|
email,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
nanoId,
|
||||||
|
domainUrl,
|
||||||
|
semver,
|
||||||
|
latLong,
|
||||||
|
macAddress,
|
||||||
|
ip,
|
||||||
|
ipv6,
|
||||||
|
number,
|
||||||
|
} from 'minifaker';
|
||||||
|
import 'minifaker/locales/en';
|
||||||
|
|
||||||
|
export function generateRandomUser() {
|
||||||
|
return {
|
||||||
|
uid: uuid.v4(),
|
||||||
|
email: email(),
|
||||||
|
firstname: firstName(),
|
||||||
|
lastname: lastName(),
|
||||||
|
password: password(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateRandomAddress() {
|
||||||
|
return {
|
||||||
|
firstname: firstName(),
|
||||||
|
lastname: lastName(),
|
||||||
|
street: streetAddress(),
|
||||||
|
city: cityName(),
|
||||||
|
zip: zipCode({ format: '#####' }),
|
||||||
|
state: state(),
|
||||||
|
country: country(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateRandomEmail() {
|
||||||
|
return {
|
||||||
|
email: email(),
|
||||||
|
confirmed: boolean(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateUUID() {
|
||||||
|
return { uuid: uuid.v4() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateNanoid(customAlphabet: string, length: string) {
|
||||||
|
return { nanoId: nanoId.customAlphabet(customAlphabet, parseInt(length, 10))().toString() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateCreditCard() {
|
||||||
|
return {
|
||||||
|
type: boolean() ? 'MasterCard' : 'Visa',
|
||||||
|
number: creditCardNumber(),
|
||||||
|
ccv: creditCardCVV(),
|
||||||
|
exp: `${number({ min: 1, max: 12, float: false }).toString().padStart(2, '0')}/${number({
|
||||||
|
min: 1,
|
||||||
|
max: 40,
|
||||||
|
float: false,
|
||||||
|
})
|
||||||
|
.toString()
|
||||||
|
.padStart(2, '0')}`,
|
||||||
|
holder_name: `${firstName()} ${lastName()}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateURL() {
|
||||||
|
return { url: domainUrl() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateIPv4() {
|
||||||
|
return { ip: ip() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateIPv6() {
|
||||||
|
return { ipv6: ipv6() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateMAC() {
|
||||||
|
return { mac: macAddress() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateLocation() {
|
||||||
|
return { location: latLong() };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateVersion() {
|
||||||
|
return { version: semver() };
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import flow from 'lodash.flow';
|
import flow from 'lodash/flow';
|
||||||
import sortBy from 'lodash.sortby';
|
import sortBy from 'lodash/sortBy';
|
||||||
import uniqBy from 'lodash.uniqby';
|
import uniqBy from 'lodash/uniqBy';
|
||||||
|
|
||||||
export type DocumentProperties = {
|
export type DocumentProperties = {
|
||||||
customProperty: Array<{ field: string; value: string }>;
|
customProperty: Array<{ field: string; value: string }>;
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { documentFields, documentOperations, indexFields, indexOperations } from
|
||||||
|
|
||||||
import type { DocumentGetAllOptions, FieldsUiValues } from './types';
|
import type { DocumentGetAllOptions, FieldsUiValues } from './types';
|
||||||
|
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
export class Elasticsearch implements INodeType {
|
export class Elasticsearch implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
|
|
@ -21,8 +21,8 @@ import { connect as imapConnect, getParts } from 'imap-simple';
|
||||||
import type { Source as ParserSource } from 'mailparser';
|
import type { Source as ParserSource } from 'mailparser';
|
||||||
import { simpleParser } from 'mailparser';
|
import { simpleParser } from 'mailparser';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import find from 'lodash.find';
|
import find from 'lodash/find';
|
||||||
|
|
||||||
export async function parseRawEmail(
|
export async function parseRawEmail(
|
||||||
this: ITriggerFunctions,
|
this: ITriggerFunctions,
|
||||||
|
|
|
@ -20,8 +20,8 @@ import { connect as imapConnect, getParts } from 'imap-simple';
|
||||||
import type { Source as ParserSource } from 'mailparser';
|
import type { Source as ParserSource } from 'mailparser';
|
||||||
import { simpleParser } from 'mailparser';
|
import { simpleParser } from 'mailparser';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import find from 'lodash.find';
|
import find from 'lodash/find';
|
||||||
import type { ICredentialsDataImap } from '../../../credentials/Imap.credentials';
|
import type { ICredentialsDataImap } from '../../../credentials/Imap.credentials';
|
||||||
import { isCredentialsDataImap } from '../../../credentials/Imap.credentials';
|
import { isCredentialsDataImap } from '../../../credentials/Imap.credentials';
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { campaignFields, campaignOperations } from './CampaignDescription';
|
||||||
|
|
||||||
import { contactListFields, contactListOperations } from './ContactListDescription';
|
import { contactListFields, contactListOperations } from './ContactListDescription';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
export class Emelia implements INodeType {
|
export class Emelia implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import type {
|
||||||
|
|
||||||
import type { OptionsWithUri } from 'request';
|
import type { OptionsWithUri } from 'request';
|
||||||
|
|
||||||
import omit from 'lodash.omit';
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
export async function freshserviceApiRequest(
|
export async function freshserviceApiRequest(
|
||||||
this: IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions,
|
this: IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions,
|
||||||
|
|
|
@ -15,7 +15,7 @@ import type {
|
||||||
ViewsResponse,
|
ViewsResponse,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
export async function freshworksCrmApiRequest(
|
export async function freshworksCrmApiRequest(
|
||||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||||
|
|
|
@ -35,8 +35,8 @@ import {
|
||||||
loadWebinarSessions,
|
loadWebinarSessions,
|
||||||
} from './GenericFunctions';
|
} from './GenericFunctions';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,14 @@ import { NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
export interface IEmail {
|
export interface IEmail {
|
||||||
from?: string;
|
from?: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
cc?: string;
|
cc?: string;
|
||||||
bcc?: string;
|
bcc?: string;
|
||||||
|
replyTo?: string;
|
||||||
inReplyTo?: string;
|
inReplyTo?: string;
|
||||||
reference?: string;
|
reference?: string;
|
||||||
subject: string;
|
subject: string;
|
||||||
|
@ -222,6 +223,7 @@ export async function encodeEmail(email: IEmail) {
|
||||||
to: email.to,
|
to: email.to,
|
||||||
cc: email.cc,
|
cc: email.cc,
|
||||||
bcc: email.bcc,
|
bcc: email.bcc,
|
||||||
|
replyTo: email.replyTo,
|
||||||
inReplyTo: email.inReplyTo,
|
inReplyTo: email.inReplyTo,
|
||||||
references: email.reference,
|
references: email.reference,
|
||||||
subject: email.subject,
|
subject: email.subject,
|
||||||
|
@ -509,7 +511,7 @@ export function unescapeSnippets(items: INodeExecutionData[]) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function replayToEmail(
|
export async function replyToEmail(
|
||||||
this: IExecuteFunctions,
|
this: IExecuteFunctions,
|
||||||
items: INodeExecutionData[],
|
items: INodeExecutionData[],
|
||||||
gmailId: string,
|
gmailId: string,
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { labelFields, labelOperations } from './LabelDescription';
|
||||||
|
|
||||||
import { draftFields, draftOperations } from './DraftDescription';
|
import { draftFields, draftOperations } from './DraftDescription';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
import { oldVersionNotice } from '../../../../utils/descriptions';
|
import { oldVersionNotice } from '../../../../utils/descriptions';
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,14 @@ export const draftFields: INodeProperties[] = [
|
||||||
placeholder: 'info@example.com',
|
placeholder: 'info@example.com',
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Send Replies To',
|
||||||
|
name: 'replyTo',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'reply@example.com',
|
||||||
|
default: '',
|
||||||
|
description: 'The email address that the reply message is sent to',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Attachments',
|
displayName: 'Attachments',
|
||||||
name: 'attachmentsUi',
|
name: 'attachmentsUi',
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
prepareEmailBody,
|
prepareEmailBody,
|
||||||
prepareEmailsInput,
|
prepareEmailsInput,
|
||||||
prepareQuery,
|
prepareQuery,
|
||||||
replayToEmail,
|
replyToEmail,
|
||||||
simplifyOutput,
|
simplifyOutput,
|
||||||
unescapeSnippets,
|
unescapeSnippets,
|
||||||
} from '../GenericFunctions';
|
} from '../GenericFunctions';
|
||||||
|
@ -282,6 +282,7 @@ export class GmailV2 implements INodeType {
|
||||||
const to = prepareEmailsInput.call(this, sendTo, 'To', i);
|
const to = prepareEmailsInput.call(this, sendTo, 'To', i);
|
||||||
let cc = '';
|
let cc = '';
|
||||||
let bcc = '';
|
let bcc = '';
|
||||||
|
let replyTo = '';
|
||||||
|
|
||||||
if (options.ccList) {
|
if (options.ccList) {
|
||||||
cc = prepareEmailsInput.call(this, options.ccList as string, 'CC', i);
|
cc = prepareEmailsInput.call(this, options.ccList as string, 'CC', i);
|
||||||
|
@ -291,6 +292,10 @@ export class GmailV2 implements INodeType {
|
||||||
bcc = prepareEmailsInput.call(this, options.bccList as string, 'BCC', i);
|
bcc = prepareEmailsInput.call(this, options.bccList as string, 'BCC', i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.replyTo) {
|
||||||
|
replyTo = prepareEmailsInput.call(this, options.replyTo as string, 'ReplyTo', i);
|
||||||
|
}
|
||||||
|
|
||||||
let attachments: IDataObject[] = [];
|
let attachments: IDataObject[] = [];
|
||||||
|
|
||||||
if (options.attachmentsUi) {
|
if (options.attachmentsUi) {
|
||||||
|
@ -323,6 +328,7 @@ export class GmailV2 implements INodeType {
|
||||||
to,
|
to,
|
||||||
cc,
|
cc,
|
||||||
bcc,
|
bcc,
|
||||||
|
replyTo,
|
||||||
subject: this.getNodeParameter('subject', i) as string,
|
subject: this.getNodeParameter('subject', i) as string,
|
||||||
...prepareEmailBody.call(this, i),
|
...prepareEmailBody.call(this, i),
|
||||||
attachments,
|
attachments,
|
||||||
|
@ -340,7 +346,7 @@ export class GmailV2 implements INodeType {
|
||||||
const messageIdGmail = this.getNodeParameter('messageId', i) as string;
|
const messageIdGmail = this.getNodeParameter('messageId', i) as string;
|
||||||
const options = this.getNodeParameter('options', i);
|
const options = this.getNodeParameter('options', i);
|
||||||
|
|
||||||
responseData = await replayToEmail.call(this, items, messageIdGmail, options, i);
|
responseData = await replyToEmail.call(this, items, messageIdGmail, options, i);
|
||||||
}
|
}
|
||||||
if (operation === 'get') {
|
if (operation === 'get') {
|
||||||
//https://developers.google.com/gmail/api/v1/reference/users/messages/get
|
//https://developers.google.com/gmail/api/v1/reference/users/messages/get
|
||||||
|
@ -514,6 +520,7 @@ export class GmailV2 implements INodeType {
|
||||||
let to = '';
|
let to = '';
|
||||||
let cc = '';
|
let cc = '';
|
||||||
let bcc = '';
|
let bcc = '';
|
||||||
|
let replyTo = '';
|
||||||
|
|
||||||
if (options.sendTo) {
|
if (options.sendTo) {
|
||||||
to += prepareEmailsInput.call(this, options.sendTo as string, 'To', i);
|
to += prepareEmailsInput.call(this, options.sendTo as string, 'To', i);
|
||||||
|
@ -527,6 +534,10 @@ export class GmailV2 implements INodeType {
|
||||||
bcc = prepareEmailsInput.call(this, options.bccList as string, 'BCC', i);
|
bcc = prepareEmailsInput.call(this, options.bccList as string, 'BCC', i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.replyTo) {
|
||||||
|
replyTo = prepareEmailsInput.call(this, options.replyTo as string, 'ReplyTo', i);
|
||||||
|
}
|
||||||
|
|
||||||
let attachments: IDataObject[] = [];
|
let attachments: IDataObject[] = [];
|
||||||
if (options.attachmentsUi) {
|
if (options.attachmentsUi) {
|
||||||
attachments = await prepareEmailAttachments.call(
|
attachments = await prepareEmailAttachments.call(
|
||||||
|
@ -547,6 +558,7 @@ export class GmailV2 implements INodeType {
|
||||||
to,
|
to,
|
||||||
cc,
|
cc,
|
||||||
bcc,
|
bcc,
|
||||||
|
replyTo,
|
||||||
subject: this.getNodeParameter('subject', i) as string,
|
subject: this.getNodeParameter('subject', i) as string,
|
||||||
...prepareEmailBody.call(this, i),
|
...prepareEmailBody.call(this, i),
|
||||||
attachments,
|
attachments,
|
||||||
|
@ -741,7 +753,7 @@ export class GmailV2 implements INodeType {
|
||||||
const messageIdGmail = this.getNodeParameter('messageId', i) as string;
|
const messageIdGmail = this.getNodeParameter('messageId', i) as string;
|
||||||
const options = this.getNodeParameter('options', i);
|
const options = this.getNodeParameter('options', i);
|
||||||
|
|
||||||
responseData = await replayToEmail.call(this, items, messageIdGmail, options, i);
|
responseData = await replyToEmail.call(this, items, messageIdGmail, options, i);
|
||||||
}
|
}
|
||||||
if (operation === 'trash') {
|
if (operation === 'trash') {
|
||||||
//https://developers.google.com/gmail/api/reference/rest/v1/users.threads/trash
|
//https://developers.google.com/gmail/api/reference/rest/v1/users.threads/trash
|
||||||
|
|
|
@ -225,6 +225,19 @@ export const messageFields: INodeProperties[] = [
|
||||||
default: '',
|
default: '',
|
||||||
description: "The name that will be shown in recipients' inboxes",
|
description: "The name that will be shown in recipients' inboxes",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Send Replies To',
|
||||||
|
name: 'replyTo',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'reply@example.com',
|
||||||
|
default: '',
|
||||||
|
description: 'The email address that the reply message is sent to',
|
||||||
|
displayOptions: {
|
||||||
|
hide: {
|
||||||
|
'/operation': ['reply'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Reply to Sender Only',
|
displayName: 'Reply to Sender Only',
|
||||||
name: 'replyToSenderOnly',
|
name: 'replyToSenderOnly',
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { apiRequest } from './v2/transport';
|
||||||
import type { SheetDataRow, SheetRangeData } from './v2/helpers/GoogleSheets.types';
|
import type { SheetDataRow, SheetRangeData } from './v2/helpers/GoogleSheets.types';
|
||||||
|
|
||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
import isEqual from 'lodash.isequal';
|
import isEqual from 'lodash/isEqual';
|
||||||
import zip from 'lodash.zip';
|
import zip from 'lodash/zip';
|
||||||
|
|
||||||
export const BINARY_MIME_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
export const BINARY_MIME_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { googleApiRequest } from './GenericFunctions';
|
||||||
|
|
||||||
import { utils as xlsxUtils } from 'xlsx';
|
import { utils as xlsxUtils } from 'xlsx';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
export interface ISheetOptions {
|
export interface ISheetOptions {
|
||||||
scope: string[];
|
scope: string[];
|
||||||
|
|
|
@ -7,7 +7,7 @@ import type {
|
||||||
import { NodeOperationError } from 'n8n-workflow';
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
import { apiRequest } from '../transport';
|
import { apiRequest } from '../transport';
|
||||||
import { utils as xlsxUtils } from 'xlsx';
|
import { utils as xlsxUtils } from 'xlsx';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import type {
|
import type {
|
||||||
ILookupValues,
|
ILookupValues,
|
||||||
ISheetUpdateData,
|
ISheetUpdateData,
|
||||||
|
|
|
@ -10,7 +10,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
export async function helpscoutApiRequest(
|
export async function helpscoutApiRequest(
|
||||||
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IHookFunctions,
|
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IHookFunctions,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeOperationError } from 'n8n-workflow';
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
type Cheerio = ReturnType<typeof cheerio>;
|
type Cheerio = ReturnType<typeof cheerio>;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { IDataObject, INodeExecutionData, IOAuth2Options } from 'n8n-workflow';
|
import type { IDataObject, INodeExecutionData, IOAuth2Options } from 'n8n-workflow';
|
||||||
import type { OptionsWithUri } from 'request-promise-native';
|
import type { OptionsWithUri } from 'request-promise-native';
|
||||||
|
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
|
|
||||||
export type BodyParameter = { name: string; value: string };
|
export type BodyParameter = { name: string; value: string };
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
|
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
export const eventID: { [key: string]: string } = {
|
export const eventID: { [key: string]: string } = {
|
||||||
create_client: '1',
|
create_client: '1',
|
||||||
|
|
|
@ -12,16 +12,16 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeOperationError } from 'n8n-workflow';
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import isEqual from 'lodash.isequal';
|
import isEqual from 'lodash/isEqual';
|
||||||
import isObject from 'lodash.isobject';
|
import isObject from 'lodash/isObject';
|
||||||
import lt from 'lodash.lt';
|
import lt from 'lodash/lt';
|
||||||
import merge from 'lodash.merge';
|
import merge from 'lodash/merge';
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
import reduce from 'lodash.reduce';
|
import reduce from 'lodash/reduce';
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import unset from 'lodash.unset';
|
import unset from 'lodash/unset';
|
||||||
|
|
||||||
const compareItems = (
|
const compareItems = (
|
||||||
obj: INodeExecutionData,
|
obj: INodeExecutionData,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeOperationError } from 'n8n-workflow';
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
type AggregationType =
|
type AggregationType =
|
||||||
| 'append'
|
| 'append'
|
||||||
|
|
|
@ -12,16 +12,16 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeOperationError, deepCopy } from 'n8n-workflow';
|
import { NodeOperationError, deepCopy } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import isEqual from 'lodash.isequal';
|
import isEqual from 'lodash/isEqual';
|
||||||
import isObject from 'lodash.isobject';
|
import isObject from 'lodash/isObject';
|
||||||
import lt from 'lodash.lt';
|
import lt from 'lodash/lt';
|
||||||
import merge from 'lodash.merge';
|
import merge from 'lodash/merge';
|
||||||
import pick from 'lodash.pick';
|
import pick from 'lodash/pick';
|
||||||
import reduce from 'lodash.reduce';
|
import reduce from 'lodash/reduce';
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import unset from 'lodash.unset';
|
import unset from 'lodash/unset';
|
||||||
|
|
||||||
const compareItems = (
|
const compareItems = (
|
||||||
obj: INodeExecutionData,
|
obj: INodeExecutionData,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeOperationError } from 'n8n-workflow';
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
type AggregationType =
|
type AggregationType =
|
||||||
| 'append'
|
| 'append'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
import mergeWith from 'lodash.mergewith';
|
import mergeWith from 'lodash/mergeWith';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
IBinaryKeyData,
|
IBinaryKeyData,
|
||||||
|
|
|
@ -9,21 +9,21 @@ import type {
|
||||||
IWebhookFunctions,
|
IWebhookFunctions,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import concat from 'lodash.concat';
|
import concat from 'lodash/concat';
|
||||||
import split from 'lodash.split';
|
import split from 'lodash/split';
|
||||||
import every from 'lodash.every';
|
import every from 'lodash/every';
|
||||||
import toString from 'lodash.tostring';
|
import toString from 'lodash/toString';
|
||||||
import toNumber from 'lodash.tonumber';
|
import toNumber from 'lodash/toNumber';
|
||||||
import isString from 'lodash.isstring';
|
import isString from 'lodash/isString';
|
||||||
import compact from 'lodash.compact';
|
import compact from 'lodash/compact';
|
||||||
import first from 'lodash.first';
|
import first from 'lodash/first';
|
||||||
import last from 'lodash.last';
|
import last from 'lodash/last';
|
||||||
import clone from 'lodash.clone';
|
import clone from 'lodash/clone';
|
||||||
import some from 'lodash.some';
|
import some from 'lodash/some';
|
||||||
import isArray from 'lodash.isarray';
|
import isArray from 'lodash/isArray';
|
||||||
import trim from 'lodash.trim';
|
import trim from 'lodash/trim';
|
||||||
import escapeRegExp from 'lodash.escaperegexp';
|
import escapeRegExp from 'lodash/escapeRegExp';
|
||||||
|
|
||||||
export async function koBoToolboxApiRequest(
|
export async function koBoToolboxApiRequest(
|
||||||
this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions,
|
this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions,
|
||||||
|
|
|
@ -22,8 +22,8 @@ import {
|
||||||
|
|
||||||
import { lemlistApiRequest, lemlistApiRequestAllItems } from './GenericFunctions';
|
import { lemlistApiRequest, lemlistApiRequestAllItems } from './GenericFunctions';
|
||||||
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
export class Lemlist implements INodeType {
|
export class Lemlist implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import { query } from './Queries';
|
import { query } from './Queries';
|
||||||
|
|
||||||
|
|
|
@ -113,9 +113,6 @@ export class LinkedIn implements INodeType {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (shareMediaCategory === 'IMAGE') {
|
if (shareMediaCategory === 'IMAGE') {
|
||||||
if (additionalFields.description) {
|
|
||||||
description = additionalFields.description as string;
|
|
||||||
}
|
|
||||||
if (additionalFields.title) {
|
if (additionalFields.title) {
|
||||||
title = additionalFields.title as string;
|
title = additionalFields.title as string;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +142,6 @@ export class LinkedIn implements INodeType {
|
||||||
media: {
|
media: {
|
||||||
title,
|
title,
|
||||||
id: image,
|
id: image,
|
||||||
description,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
commentary: text,
|
commentary: text,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue