mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
fix: Lazy load nodes for credentials testing (#4760)
This commit is contained in:
parent
3d67df490c
commit
0a7a2f3e41
|
@ -18,6 +18,10 @@ class CredentialTypesClass implements ICredentialTypes {
|
||||||
return this.getCredential(credentialType).type;
|
return this.getCredential(credentialType).type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNodeTypesToTestWith(type: string): string[] {
|
||||||
|
return this.knownCredentials[type]?.nodesToTestWith ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
private getCredential(type: string): LoadedClass<ICredentialType> {
|
private getCredential(type: string): LoadedClass<ICredentialType> {
|
||||||
const loadedCredentials = this.loadedCredentials;
|
const loadedCredentials = this.loadedCredentials;
|
||||||
if (type in loadedCredentials) {
|
if (type in loadedCredentials) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ import {
|
||||||
IHttpRequestHelper,
|
IHttpRequestHelper,
|
||||||
INodeTypeData,
|
INodeTypeData,
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
|
ICredentialTypes,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import * as Db from '@/Db';
|
import * as Db from '@/Db';
|
||||||
|
@ -47,25 +48,48 @@ import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'
|
||||||
import { User } from '@db/entities/User';
|
import { User } from '@db/entities/User';
|
||||||
import { CredentialsEntity } from '@db/entities/CredentialsEntity';
|
import { CredentialsEntity } from '@db/entities/CredentialsEntity';
|
||||||
import { NodeTypes } from '@/NodeTypes';
|
import { NodeTypes } from '@/NodeTypes';
|
||||||
import { CredentialsOverwrites } from '@/CredentialsOverwrites';
|
|
||||||
import { CredentialTypes } from '@/CredentialTypes';
|
import { CredentialTypes } from '@/CredentialTypes';
|
||||||
|
import { CredentialsOverwrites } from '@/CredentialsOverwrites';
|
||||||
import { whereClause } from './UserManagement/UserManagementHelper';
|
import { whereClause } from './UserManagement/UserManagementHelper';
|
||||||
|
import { RESPONSE_ERROR_MESSAGES } from './constants';
|
||||||
|
|
||||||
const mockNodesData: INodeTypeData = {};
|
const mockNode = {
|
||||||
const mockNodeTypes: INodeTypes = {
|
name: '',
|
||||||
getAll(): Array<INodeType | IVersionedNodeType> {
|
typeVersion: 1,
|
||||||
return Object.values(mockNodesData).map((data) => data.type);
|
type: 'mock',
|
||||||
|
position: [0, 0],
|
||||||
|
parameters: {} as INodeParameters,
|
||||||
|
} as INode;
|
||||||
|
|
||||||
|
const mockNodesData: INodeTypeData = {
|
||||||
|
mock: {
|
||||||
|
sourcePath: '',
|
||||||
|
type: {
|
||||||
|
description: { properties: [] as INodeProperties[] },
|
||||||
|
} as INodeType,
|
||||||
},
|
},
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined {
|
};
|
||||||
if (mockNodesData[nodeType] === undefined) {
|
|
||||||
return undefined;
|
const mockNodeTypes: INodeTypes = {
|
||||||
|
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
||||||
|
return mockNodesData[nodeType]?.type;
|
||||||
|
},
|
||||||
|
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
||||||
|
if (!mockNodesData[nodeType]) {
|
||||||
|
throw new Error(`${RESPONSE_ERROR_MESSAGES.NO_NODE}: ${nodeType}`);
|
||||||
}
|
}
|
||||||
return NodeHelpers.getVersionedNodeType(mockNodesData[nodeType].type, version);
|
return NodeHelpers.getVersionedNodeType(mockNodesData[nodeType].type, version);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CredentialsHelper extends ICredentialsHelper {
|
export class CredentialsHelper extends ICredentialsHelper {
|
||||||
private credentialTypes = CredentialTypes();
|
constructor(
|
||||||
|
encryptionKey: string,
|
||||||
|
private credentialTypes: ICredentialTypes = CredentialTypes(),
|
||||||
|
private nodeTypes: INodeTypes = NodeTypes(),
|
||||||
|
) {
|
||||||
|
super(encryptionKey);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the required authentication information to the request
|
* Add the required authentication information to the request
|
||||||
|
@ -387,16 +411,8 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const node = {
|
|
||||||
name: '',
|
|
||||||
typeVersion: 1,
|
|
||||||
type: 'mock',
|
|
||||||
position: [0, 0],
|
|
||||||
parameters: {} as INodeParameters,
|
|
||||||
} as INode;
|
|
||||||
|
|
||||||
const workflow = new Workflow({
|
const workflow = new Workflow({
|
||||||
nodes: [node],
|
nodes: [mockNode],
|
||||||
connections: {},
|
connections: {},
|
||||||
active: false,
|
active: false,
|
||||||
nodeTypes: mockNodeTypes,
|
nodeTypes: mockNodeTypes,
|
||||||
|
@ -404,7 +420,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
|
|
||||||
// Resolve expressions if any are set
|
// Resolve expressions if any are set
|
||||||
decryptedData = workflow.expression.getComplexParameterValue(
|
decryptedData = workflow.expression.getComplexParameterValue(
|
||||||
node,
|
mockNode,
|
||||||
decryptedData as INodeParameters,
|
decryptedData as INodeParameters,
|
||||||
mode,
|
mode,
|
||||||
defaultTimezone,
|
defaultTimezone,
|
||||||
|
@ -457,28 +473,27 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
await Db.collections.Credentials.update(findQuery, newCredentialsData);
|
await Db.collections.Credentials.update(findQuery, newCredentialsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCredentialTestFunction(
|
private getCredentialTestFunction(
|
||||||
credentialType: string,
|
credentialType: string,
|
||||||
nodeToTestWith?: string,
|
|
||||||
): ICredentialTestFunction | ICredentialTestRequestData | undefined {
|
): ICredentialTestFunction | ICredentialTestRequestData | undefined {
|
||||||
const nodeTypes = NodeTypes();
|
// Check if test is defined on credentials
|
||||||
const allNodes = nodeTypes.getAll();
|
const type = this.credentialTypes.getByName(credentialType);
|
||||||
|
if (type.test) {
|
||||||
|
return {
|
||||||
|
testRequest: type.test,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Check all the nodes one by one if they have a test function defined
|
const nodeTypesToTestWith = this.credentialTypes.getNodeTypesToTestWith(credentialType);
|
||||||
for (let i = 0; i < allNodes.length; i++) {
|
for (const nodeName of nodeTypesToTestWith) {
|
||||||
const node = allNodes[i];
|
const node = this.nodeTypes.getByName(nodeName);
|
||||||
|
|
||||||
if (nodeToTestWith && node.description.name !== nodeToTestWith) {
|
|
||||||
// eslint-disable-next-line no-continue
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always set to an array even if node is not versioned to not having
|
// Always set to an array even if node is not versioned to not having
|
||||||
// to duplicate the logic
|
// to duplicate the logic
|
||||||
const allNodeTypes: INodeType[] = [];
|
const allNodeTypes: INodeType[] = [];
|
||||||
if (node instanceof VersionedNodeType) {
|
if (node instanceof VersionedNodeType) {
|
||||||
// Node is versioned
|
// Node is versioned
|
||||||
allNodeTypes.push(...Object.values((node as IVersionedNodeType).nodeVersions));
|
allNodeTypes.push(...Object.values(node.nodeVersions));
|
||||||
} else {
|
} else {
|
||||||
// Node is not versioned
|
// Node is not versioned
|
||||||
allNodeTypes.push(node as INodeType);
|
allNodeTypes.push(node as INodeType);
|
||||||
|
@ -487,49 +502,35 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
// Check each of the node versions for credential tests
|
// Check each of the node versions for credential tests
|
||||||
for (const nodeType of allNodeTypes) {
|
for (const nodeType of allNodeTypes) {
|
||||||
// Check each of teh credentials
|
// Check each of teh credentials
|
||||||
for (const credential of nodeType.description.credentials ?? []) {
|
for (const { name, testedBy } of nodeType.description.credentials ?? []) {
|
||||||
if (credential.name === credentialType && !!credential.testedBy) {
|
if (name === credentialType && !!testedBy) {
|
||||||
if (typeof credential.testedBy === 'string') {
|
if (typeof testedBy === 'string') {
|
||||||
if (Object.prototype.hasOwnProperty.call(node, 'nodeVersions')) {
|
if (node instanceof VersionedNodeType) {
|
||||||
// The node is versioned. So check all versions for test function
|
// The node is versioned. So check all versions for test function
|
||||||
// starting with the latest
|
// starting with the latest
|
||||||
const versions = Object.keys((node as IVersionedNodeType).nodeVersions)
|
const versions = Object.keys(node.nodeVersions).sort().reverse();
|
||||||
.sort()
|
|
||||||
.reverse();
|
|
||||||
for (const version of versions) {
|
for (const version of versions) {
|
||||||
const versionedNode = (node as IVersionedNodeType).nodeVersions[
|
const versionedNode = node.nodeVersions[parseInt(version, 10)];
|
||||||
parseInt(version, 10)
|
const credentialTest = versionedNode.methods?.credentialTest;
|
||||||
];
|
if (credentialTest && testedBy in credentialTest) {
|
||||||
if (
|
return credentialTest[testedBy];
|
||||||
versionedNode.methods?.credentialTest &&
|
|
||||||
versionedNode.methods?.credentialTest[credential.testedBy]
|
|
||||||
) {
|
|
||||||
return versionedNode.methods?.credentialTest[credential.testedBy];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Test is defined as string which links to a function
|
// Test is defined as string which links to a function
|
||||||
return (node as unknown as INodeType).methods?.credentialTest![credential.testedBy];
|
return (node as unknown as INodeType).methods?.credentialTest![testedBy];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test is defined as JSON with a definition for the request to make
|
// Test is defined as JSON with a definition for the request to make
|
||||||
return {
|
return {
|
||||||
nodeType,
|
nodeType,
|
||||||
testRequest: credential.testedBy,
|
testRequest: testedBy,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if test is defined on credentials
|
|
||||||
const type = this.credentialTypes.getByName(credentialType);
|
|
||||||
if (type.test) {
|
|
||||||
return {
|
|
||||||
testRequest: type.test,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,9 +538,8 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
user: User,
|
user: User,
|
||||||
credentialType: string,
|
credentialType: string,
|
||||||
credentialsDecrypted: ICredentialsDecrypted,
|
credentialsDecrypted: ICredentialsDecrypted,
|
||||||
nodeToTestWith?: string,
|
|
||||||
): Promise<INodeCredentialTestResult> {
|
): Promise<INodeCredentialTestResult> {
|
||||||
const credentialTestFunction = this.getCredentialTestFunction(credentialType, nodeToTestWith);
|
const credentialTestFunction = this.getCredentialTestFunction(credentialType);
|
||||||
if (credentialTestFunction === undefined) {
|
if (credentialTestFunction === undefined) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
status: 'Error',
|
status: 'Error',
|
||||||
|
@ -570,8 +570,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
if (credentialTestFunction.nodeType) {
|
if (credentialTestFunction.nodeType) {
|
||||||
nodeType = credentialTestFunction.nodeType;
|
nodeType = credentialTestFunction.nodeType;
|
||||||
} else {
|
} else {
|
||||||
const nodeTypes = NodeTypes();
|
nodeType = this.nodeTypes.getByNameAndVersion('n8n-nodes-base.noOp');
|
||||||
nodeType = nodeTypes.getByNameAndVersion('n8n-nodes-base.noOp');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const node: INode = {
|
const node: INode = {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import type {
|
||||||
ITelemetrySettings,
|
ITelemetrySettings,
|
||||||
ITelemetryTrackProperties,
|
ITelemetryTrackProperties,
|
||||||
IWorkflowBase as IWorkflowBaseWorkflow,
|
IWorkflowBase as IWorkflowBaseWorkflow,
|
||||||
LoadingDetails,
|
CredentialLoadingDetails,
|
||||||
Workflow,
|
Workflow,
|
||||||
WorkflowActivateMode,
|
WorkflowActivateMode,
|
||||||
WorkflowExecuteMode,
|
WorkflowExecuteMode,
|
||||||
|
@ -59,7 +59,7 @@ export interface ICustomRequest extends Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICredentialsTypeData {
|
export interface ICredentialsTypeData {
|
||||||
[key: string]: LoadingDetails;
|
[key: string]: CredentialLoadingDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICredentialsOverwrite {
|
export interface ICredentialsOverwrite {
|
||||||
|
|
|
@ -366,8 +366,12 @@ export class LoadNodesAndCredentialsClass implements INodesAndCredentials {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const type in known.credentials) {
|
for (const type in known.credentials) {
|
||||||
const { className, sourcePath } = known.credentials[type];
|
const { className, sourcePath, nodesToTestWith } = known.credentials[type];
|
||||||
this.known.credentials[type] = { className, sourcePath: path.join(dir, sourcePath) };
|
this.known.credentials[type] = {
|
||||||
|
className,
|
||||||
|
sourcePath: path.join(dir, sourcePath),
|
||||||
|
nodesToTestWith: nodesToTestWith?.map((nodeName) => `${packageName}.${nodeName}`),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,6 @@ class NodeTypesClass implements INodeTypes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll(): Array<INodeType | IVersionedNodeType> {
|
|
||||||
return Object.values(this.loadedNodes).map(({ type }) => type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variant of `getByNameAndVersion` that includes the node's source path, used to locate a node's translations.
|
* Variant of `getByNameAndVersion` that includes the node's source path, used to locate a node's translations.
|
||||||
*/
|
*/
|
||||||
|
@ -43,6 +39,10 @@ class NodeTypesClass implements INodeTypes {
|
||||||
return { description: { ...description }, sourcePath: nodeType.sourcePath };
|
return { description: { ...description }, sourcePath: nodeType.sourcePath };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
||||||
|
return this.getNode(nodeType).type;
|
||||||
|
}
|
||||||
|
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
||||||
return NodeHelpers.getVersionedNodeType(this.getNode(nodeType).type, version);
|
return NodeHelpers.getVersionedNodeType(this.getNode(nodeType).type, version);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ EECredentialsController.get(
|
||||||
EECredentialsController.post(
|
EECredentialsController.post(
|
||||||
'/test',
|
'/test',
|
||||||
ResponseHelper.send(async (req: CredentialRequest.Test): Promise<INodeCredentialTestResult> => {
|
ResponseHelper.send(async (req: CredentialRequest.Test): Promise<INodeCredentialTestResult> => {
|
||||||
const { credentials, nodeToTestWith } = req.body;
|
const { credentials } = req.body;
|
||||||
|
|
||||||
const encryptionKey = await EECredentials.getEncryptionKey();
|
const encryptionKey = await EECredentials.getEncryptionKey();
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ EECredentialsController.post(
|
||||||
Object.assign(credentials, { data: decryptedData });
|
Object.assign(credentials, { data: decryptedData });
|
||||||
}
|
}
|
||||||
|
|
||||||
return EECredentials.test(req.user, encryptionKey, credentials, nodeToTestWith);
|
return EECredentials.test(req.user, encryptionKey, credentials);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -113,10 +113,10 @@ credentialsController.get(
|
||||||
credentialsController.post(
|
credentialsController.post(
|
||||||
'/test',
|
'/test',
|
||||||
ResponseHelper.send(async (req: CredentialRequest.Test): Promise<INodeCredentialTestResult> => {
|
ResponseHelper.send(async (req: CredentialRequest.Test): Promise<INodeCredentialTestResult> => {
|
||||||
const { credentials, nodeToTestWith } = req.body;
|
const { credentials } = req.body;
|
||||||
|
|
||||||
const encryptionKey = await CredentialsService.getEncryptionKey();
|
const encryptionKey = await CredentialsService.getEncryptionKey();
|
||||||
return CredentialsService.test(req.user, encryptionKey, credentials, nodeToTestWith);
|
return CredentialsService.test(req.user, encryptionKey, credentials);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -282,10 +282,9 @@ export class CredentialsService {
|
||||||
user: User,
|
user: User,
|
||||||
encryptionKey: string,
|
encryptionKey: string,
|
||||||
credentials: ICredentialsDecrypted,
|
credentials: ICredentialsDecrypted,
|
||||||
nodeToTestWith: string | undefined,
|
|
||||||
): Promise<INodeCredentialTestResult> {
|
): Promise<INodeCredentialTestResult> {
|
||||||
const helper = new CredentialsHelper(encryptionKey);
|
const helper = new CredentialsHelper(encryptionKey);
|
||||||
|
|
||||||
return helper.testCredentials(user, credentials.type, credentials, nodeToTestWith);
|
return helper.testCredentials(user, credentials.type, credentials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {
|
||||||
IAuthenticateGeneric,
|
IAuthenticateGeneric,
|
||||||
ICredentialDataDecryptedObject,
|
ICredentialDataDecryptedObject,
|
||||||
ICredentialType,
|
ICredentialType,
|
||||||
ICredentialTypeData,
|
|
||||||
IHttpRequestOptions,
|
IHttpRequestOptions,
|
||||||
INode,
|
INode,
|
||||||
INodeProperties,
|
INodeProperties,
|
||||||
|
@ -234,9 +233,13 @@ describe('CredentialsHelper', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
CredentialTypes(mockNodesAndCredentials);
|
const credentialTypes = CredentialTypes(mockNodesAndCredentials);
|
||||||
|
|
||||||
const credentialsHelper = new CredentialsHelper(TEST_ENCRYPTION_KEY);
|
const credentialsHelper = new CredentialsHelper(
|
||||||
|
TEST_ENCRYPTION_KEY,
|
||||||
|
credentialTypes,
|
||||||
|
nodeTypes,
|
||||||
|
);
|
||||||
|
|
||||||
const result = await credentialsHelper.authenticate(
|
const result = await credentialsHelper.authenticate(
|
||||||
testData.input.credentials,
|
testData.input.credentials,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeData,
|
INodeTypeData,
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
|
IVersionedNodeType,
|
||||||
NodeHelpers,
|
NodeHelpers,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
@ -48,12 +49,8 @@ class NodeTypesClass implements INodeTypes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll(): INodeType[] {
|
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
||||||
return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type));
|
return this.nodeTypes[nodeType].type;
|
||||||
}
|
|
||||||
|
|
||||||
getByName(nodeType: string): INodeType {
|
|
||||||
return this.getByNameAndVersion(nodeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
||||||
|
|
|
@ -22,7 +22,9 @@ const loadClass = (sourcePath) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const generate = (kind) => {
|
const nodesToTestWith = {};
|
||||||
|
|
||||||
|
const generate = async (kind) => {
|
||||||
const data = glob
|
const data = glob
|
||||||
.sync(`dist/${kind}/**/*.${kind === 'nodes' ? 'node' : kind}.js`, {
|
.sync(`dist/${kind}/**/*.${kind === 'nodes' ? 'node' : kind}.js`, {
|
||||||
cwd: packageDir,
|
cwd: packageDir,
|
||||||
|
@ -34,12 +36,28 @@ const generate = (kind) => {
|
||||||
const name = kind === 'nodes' ? instance.description.name : instance.name;
|
const name = kind === 'nodes' ? instance.description.name : instance.name;
|
||||||
if (name in obj) console.error('already loaded', kind, name, sourcePath);
|
if (name in obj) console.error('already loaded', kind, name, sourcePath);
|
||||||
else obj[name] = { className, sourcePath };
|
else obj[name] = { className, sourcePath };
|
||||||
|
|
||||||
|
if (kind === 'nodes') {
|
||||||
|
const { credentials } = instance.description;
|
||||||
|
if (credentials && credentials.length) {
|
||||||
|
for (const credential of credentials) {
|
||||||
|
nodesToTestWith[credential.name] = nodesToTestWith[credential.name] || [];
|
||||||
|
nodesToTestWith[credential.name].push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (name in nodesToTestWith) {
|
||||||
|
obj[name].nodesToTestWith = nodesToTestWith[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
LoggerProxy.info(`Detected ${Object.keys(data).length} ${kind}`);
|
LoggerProxy.info(`Detected ${Object.keys(data).length} ${kind}`);
|
||||||
return writeJSON(`known/${kind}.json`, data);
|
await writeJSON(`known/${kind}.json`, data);
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
await Promise.all([generate('credentials'), generate('nodes')]);
|
await generate('nodes');
|
||||||
|
await generate('credentials');
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
IRun,
|
IRun,
|
||||||
ITaskData,
|
ITaskData,
|
||||||
|
IVersionedNodeType,
|
||||||
IWorkflowBase,
|
IWorkflowBase,
|
||||||
IWorkflowExecuteAdditionalData,
|
IWorkflowExecuteAdditionalData,
|
||||||
NodeHelpers,
|
NodeHelpers,
|
||||||
|
@ -805,12 +806,8 @@ class NodeTypesClass implements INodeTypes {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
getAll(): INodeType[] {
|
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
||||||
return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type));
|
return this.nodeTypes[nodeType].type;
|
||||||
}
|
|
||||||
|
|
||||||
getByName(nodeType: string): INodeType {
|
|
||||||
return this.getByNameAndVersion(nodeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
||||||
|
|
|
@ -335,10 +335,6 @@ export const workflowHelpers = mixins(
|
||||||
const nodeTypes: INodeTypes = {
|
const nodeTypes: INodeTypes = {
|
||||||
nodeTypes: {},
|
nodeTypes: {},
|
||||||
init: async (nodeTypes?: INodeTypeData): Promise<void> => { },
|
init: async (nodeTypes?: INodeTypeData): Promise<void> => { },
|
||||||
getAll: (): Array<INodeType | IVersionedNodeType> => {
|
|
||||||
// Does not get used in Workflow so no need to return it
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
getByNameAndVersion: (nodeType: string, version?: number): INodeType | undefined => {
|
getByNameAndVersion: (nodeType: string, version?: number): INodeType | undefined => {
|
||||||
const nodeTypeDescription = this.nodeTypesStore.getNodeType(nodeType, version);
|
const nodeTypeDescription = this.nodeTypesStore.getNodeType(nodeType, version);
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ export class Mocean implements INodeType {
|
||||||
|
|
||||||
let endpoint: string;
|
let endpoint: string;
|
||||||
let operation: string;
|
let operation: string;
|
||||||
let requesetMethod: string;
|
let requestMethod: string;
|
||||||
let resource: string;
|
let resource: string;
|
||||||
let text: string;
|
let text: string;
|
||||||
let dlrUrl: string;
|
let dlrUrl: string;
|
||||||
|
@ -238,7 +238,7 @@ export class Mocean implements INodeType {
|
||||||
resource = this.getNodeParameter('resource', itemIndex, '') as string;
|
resource = this.getNodeParameter('resource', itemIndex, '') as string;
|
||||||
operation = this.getNodeParameter('operation', itemIndex, '') as string;
|
operation = this.getNodeParameter('operation', itemIndex, '') as string;
|
||||||
text = this.getNodeParameter('message', itemIndex, '') as string;
|
text = this.getNodeParameter('message', itemIndex, '') as string;
|
||||||
requesetMethod = 'POST';
|
requestMethod = 'POST';
|
||||||
body['mocean-from'] = this.getNodeParameter('from', itemIndex, '') as string;
|
body['mocean-from'] = this.getNodeParameter('from', itemIndex, '') as string;
|
||||||
body['mocean-to'] = this.getNodeParameter('to', itemIndex, '') as string;
|
body['mocean-to'] = this.getNodeParameter('to', itemIndex, '') as string;
|
||||||
|
|
||||||
|
@ -271,13 +271,7 @@ export class Mocean implements INodeType {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation === 'send') {
|
if (operation === 'send') {
|
||||||
const responseData = await moceanApiRequest.call(
|
const responseData = await moceanApiRequest.call(this, requestMethod, endpoint, body, qs);
|
||||||
this,
|
|
||||||
requesetMethod,
|
|
||||||
endpoint,
|
|
||||||
body,
|
|
||||||
qs,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const item of responseData[dataKey] as IDataObject[]) {
|
for (const item of responseData[dataKey] as IDataObject[]) {
|
||||||
item.type = resource;
|
item.type = resource;
|
||||||
|
|
|
@ -181,11 +181,7 @@ export interface IHttpRequestHelper {
|
||||||
helpers: { httpRequest: IAllExecuteFunctions['helpers']['httpRequest'] };
|
helpers: { httpRequest: IAllExecuteFunctions['helpers']['httpRequest'] };
|
||||||
}
|
}
|
||||||
export abstract class ICredentialsHelper {
|
export abstract class ICredentialsHelper {
|
||||||
encryptionKey: string;
|
constructor(readonly encryptionKey: string) {}
|
||||||
|
|
||||||
constructor(encryptionKey: string) {
|
|
||||||
this.encryptionKey = encryptionKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract getParentTypes(name: string): string[];
|
abstract getParentTypes(name: string): string[];
|
||||||
|
|
||||||
|
@ -329,6 +325,7 @@ export interface ICredentialType {
|
||||||
export interface ICredentialTypes {
|
export interface ICredentialTypes {
|
||||||
recognizes(credentialType: string): boolean;
|
recognizes(credentialType: string): boolean;
|
||||||
getByName(credentialType: string): ICredentialType;
|
getByName(credentialType: string): ICredentialType;
|
||||||
|
getNodeTypesToTestWith(type: string): string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// The way the credentials get saved in the database (data encrypted)
|
// The way the credentials get saved in the database (data encrypted)
|
||||||
|
@ -1209,7 +1206,6 @@ export interface INodeCredentialTestResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INodeCredentialTestRequest {
|
export interface INodeCredentialTestRequest {
|
||||||
nodeToTestWith?: string; // node name i.e. slack
|
|
||||||
credentials: ICredentialsDecrypted;
|
credentials: ICredentialsDecrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,18 +1470,24 @@ export type WebhookResponseData = 'allEntries' | 'firstEntryJson' | 'firstEntryB
|
||||||
export type WebhookResponseMode = 'onReceived' | 'lastNode';
|
export type WebhookResponseMode = 'onReceived' | 'lastNode';
|
||||||
|
|
||||||
export interface INodeTypes {
|
export interface INodeTypes {
|
||||||
getAll(): Array<INodeType | IVersionedNodeType>;
|
getByName(nodeType: string): INodeType | IVersionedNodeType;
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined;
|
getByNameAndVersion(nodeType: string, version?: number): INodeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LoadingDetails = {
|
type LoadingDetails = {
|
||||||
className: string;
|
className: string;
|
||||||
sourcePath: string;
|
sourcePath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CredentialLoadingDetails = LoadingDetails & {
|
||||||
|
nodesToTestWith?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NodeLoadingDetails = LoadingDetails;
|
||||||
|
|
||||||
export type KnownNodesAndCredentials = {
|
export type KnownNodesAndCredentials = {
|
||||||
nodes: Record<string, LoadingDetails>;
|
nodes: Record<string, NodeLoadingDetails>;
|
||||||
credentials: Record<string, LoadingDetails>;
|
credentials: Record<string, CredentialLoadingDetails>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface LoadedClass<T> {
|
export interface LoadedClass<T> {
|
||||||
|
|
|
@ -673,12 +673,8 @@ class NodeTypesClass implements INodeTypes {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
getAll(): INodeType[] {
|
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
||||||
return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type));
|
return this.nodeTypes[nodeType].type;
|
||||||
}
|
|
||||||
|
|
||||||
getByName(nodeType: string): INodeType | IVersionedNodeType | undefined {
|
|
||||||
return this.getByNameAndVersion(nodeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
getByNameAndVersion(nodeType: string, version?: number): INodeType {
|
||||||
|
|
Loading…
Reference in a new issue