mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
extract out load-options context
This commit is contained in:
parent
47764ca805
commit
7230788438
|
@ -1,4 +1,4 @@
|
|||
import { NodeExecuteFunctions } from 'n8n-core';
|
||||
import { LoadOptionsContext, NodeExecuteFunctions } from 'n8n-core';
|
||||
import type {
|
||||
ILoadOptions,
|
||||
ILoadOptionsFunctions,
|
||||
|
@ -253,6 +253,6 @@ export class DynamicNodeParametersService {
|
|||
workflow: Workflow,
|
||||
) {
|
||||
const node = workflow.nodes['Temp-Node'];
|
||||
return NodeExecuteFunctions.getLoadOptionsFunctions(workflow, node, path, additionalData);
|
||||
return new LoadOptionsContext(workflow, node, additionalData, path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,11 @@ import type {
|
|||
} from 'axios';
|
||||
import axios from 'axios';
|
||||
import crypto, { createHmac } from 'crypto';
|
||||
import type { Request, Response } from 'express';
|
||||
import FileType from 'file-type';
|
||||
import FormData from 'form-data';
|
||||
import { createReadStream } from 'fs';
|
||||
import { access as fsAccess, writeFile as fsWriteFile } from 'fs/promises';
|
||||
import { IncomingMessage, type IncomingHttpHeaders } from 'http';
|
||||
import { IncomingMessage } from 'http';
|
||||
import { Agent, type AgentOptions } from 'https';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
@ -60,7 +59,6 @@ import type {
|
|||
IGetNodeParameterOptions,
|
||||
IHookFunctions,
|
||||
IHttpRequestOptions,
|
||||
ILoadOptionsFunctions,
|
||||
IN8nHttpFullResponse,
|
||||
IN8nHttpResponse,
|
||||
INode,
|
||||
|
@ -100,7 +98,6 @@ import type {
|
|||
INodeParameters,
|
||||
EnsureTypeOptions,
|
||||
SSHTunnelFunctions,
|
||||
SchedulingFunctions,
|
||||
DeduplicationHelperFunctions,
|
||||
IDeduplicationOutput,
|
||||
IDeduplicationOutputItems,
|
||||
|
@ -163,7 +160,6 @@ import {
|
|||
import { extractValue } from './ExtractValue';
|
||||
import { InstanceSettings } from './InstanceSettings';
|
||||
import type { ExtendedValidationResult, IResponseError } from './Interfaces';
|
||||
import { ScheduledTaskManager } from './ScheduledTaskManager';
|
||||
import { getSecretsProxy } from './Secrets';
|
||||
import { SSHClientsManager } from './SSHClientsManager';
|
||||
import { HookContext, PollContext } from './node-execution-context';
|
||||
|
@ -3591,85 +3587,6 @@ export function getCredentialTestFunctions(): ICredentialTestFunctions {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the execute functions regular nodes have access to in load-options-function.
|
||||
*/
|
||||
export function getLoadOptionsFunctions(
|
||||
workflow: Workflow,
|
||||
node: INode,
|
||||
path: string,
|
||||
additionalData: IWorkflowExecuteAdditionalData,
|
||||
): ILoadOptionsFunctions {
|
||||
return ((workflow: Workflow, node: INode, path: string) => {
|
||||
return {
|
||||
...getCommonWorkflowFunctions(workflow, node, additionalData),
|
||||
getCredentials: async (type) =>
|
||||
await getCredentials(workflow, node, type, additionalData, 'internal'),
|
||||
getCurrentNodeParameter: (
|
||||
parameterPath: string,
|
||||
options?: IGetNodeParameterOptions,
|
||||
): NodeParameterValueType | object | undefined => {
|
||||
const nodeParameters = additionalData.currentNodeParameters;
|
||||
|
||||
if (parameterPath.charAt(0) === '&') {
|
||||
parameterPath = `${path.split('.').slice(1, -1).join('.')}.${parameterPath.slice(1)}`;
|
||||
}
|
||||
|
||||
let returnData = get(nodeParameters, parameterPath);
|
||||
|
||||
// This is outside the try/catch because it throws errors with proper messages
|
||||
if (options?.extractValue) {
|
||||
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||
if (nodeType === undefined) {
|
||||
throw new ApplicationError('Node type is not known so cannot return parameter value', {
|
||||
tags: { nodeType: node.type },
|
||||
});
|
||||
}
|
||||
returnData = extractValue(
|
||||
returnData,
|
||||
parameterPath,
|
||||
node,
|
||||
nodeType,
|
||||
) as NodeParameterValueType;
|
||||
}
|
||||
|
||||
return returnData;
|
||||
},
|
||||
getCurrentNodeParameters: () => additionalData.currentNodeParameters,
|
||||
getNodeParameter: (
|
||||
parameterName: string,
|
||||
fallbackValue?: any,
|
||||
options?: IGetNodeParameterOptions,
|
||||
): NodeParameterValueType | object => {
|
||||
const runExecutionData: IRunExecutionData | null = null;
|
||||
const itemIndex = 0;
|
||||
const runIndex = 0;
|
||||
const mode = 'internal' as WorkflowExecuteMode;
|
||||
const connectionInputData: INodeExecutionData[] = [];
|
||||
|
||||
return getNodeParameter(
|
||||
workflow,
|
||||
runExecutionData,
|
||||
runIndex,
|
||||
connectionInputData,
|
||||
node,
|
||||
parameterName,
|
||||
itemIndex,
|
||||
mode,
|
||||
getAdditionalKeys(additionalData, mode, runExecutionData),
|
||||
undefined,
|
||||
fallbackValue,
|
||||
options,
|
||||
);
|
||||
},
|
||||
helpers: {
|
||||
...getSSHTunnelFunctions(),
|
||||
...getRequestHelperFunctions(workflow, node, additionalData),
|
||||
},
|
||||
};
|
||||
})(workflow, node, path);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
export function getExecuteHookFunctions(
|
||||
workflow: Workflow,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export { ExecuteSingleContext } from './execute-single-context';
|
||||
export { HookContext } from './hook-context';
|
||||
export { LoadOptionsContext } from './load-options-context';
|
||||
export { PollContext } from './poll-context';
|
||||
export { TriggerContext } from './trigger-context';
|
||||
export { WebhookContext } from './webhook-context';
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IGetNodeParameterOptions,
|
||||
INode,
|
||||
INodeExecutionData,
|
||||
ILoadOptionsFunctions,
|
||||
IRunExecutionData,
|
||||
IWorkflowExecuteAdditionalData,
|
||||
NodeParameterValueType,
|
||||
Workflow,
|
||||
} from 'n8n-workflow';
|
||||
import { ApplicationError } from 'n8n-workflow';
|
||||
|
||||
import { getAdditionalKeys, getCredentials, getNodeParameter } from '@/NodeExecuteFunctions';
|
||||
import { BaseContext } from './base-contexts';
|
||||
import { RequestHelpers } from './helpers/request-helpers';
|
||||
import { get } from 'lodash';
|
||||
import { extractValue } from '@/ExtractValue';
|
||||
import { SSHTunnelHelpers } from './helpers/ssh-tunnel-helpers';
|
||||
|
||||
export class LoadOptionsContext extends BaseContext implements ILoadOptionsFunctions {
|
||||
readonly helpers: ILoadOptionsFunctions['helpers'];
|
||||
|
||||
constructor(
|
||||
workflow: Workflow,
|
||||
node: INode,
|
||||
additionalData: IWorkflowExecuteAdditionalData,
|
||||
private readonly path: string,
|
||||
) {
|
||||
super(workflow, node, additionalData);
|
||||
|
||||
const requestHelpers = new RequestHelpers(this, workflow, node, additionalData);
|
||||
const sshTunnelHelpers = new SSHTunnelHelpers();
|
||||
|
||||
this.helpers = {
|
||||
httpRequest: requestHelpers.httpRequest.bind(requestHelpers),
|
||||
httpRequestWithAuthentication:
|
||||
requestHelpers.httpRequestWithAuthentication.bind(requestHelpers),
|
||||
requestWithAuthenticationPaginated:
|
||||
requestHelpers.requestWithAuthenticationPaginated.bind(requestHelpers),
|
||||
request: requestHelpers.request.bind(requestHelpers),
|
||||
requestWithAuthentication: requestHelpers.requestWithAuthentication.bind(requestHelpers),
|
||||
requestOAuth1: requestHelpers.requestOAuth1.bind(requestHelpers),
|
||||
requestOAuth2: requestHelpers.requestOAuth2.bind(requestHelpers),
|
||||
getSSHClient: sshTunnelHelpers.getSSHClient.bind(sshTunnelHelpers),
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: This is mostly identical to PollContext
|
||||
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {
|
||||
// TODO: move `this.mode` to the base class, instead of repeating `internal` everywhere in this class
|
||||
return await getCredentials<T>(this.workflow, this.node, type, this.additionalData, 'internal');
|
||||
}
|
||||
|
||||
getCurrentNodeParameter(
|
||||
parameterPath: string,
|
||||
options?: IGetNodeParameterOptions,
|
||||
): NodeParameterValueType | object | undefined {
|
||||
const nodeParameters = this.additionalData.currentNodeParameters;
|
||||
|
||||
if (parameterPath.charAt(0) === '&') {
|
||||
parameterPath = `${this.path.split('.').slice(1, -1).join('.')}.${parameterPath.slice(1)}`;
|
||||
}
|
||||
|
||||
let returnData = get(nodeParameters, parameterPath);
|
||||
|
||||
// This is outside the try/catch because it throws errors with proper messages
|
||||
if (options?.extractValue) {
|
||||
const nodeType = this.workflow.nodeTypes.getByNameAndVersion(
|
||||
this.node.type,
|
||||
this.node.typeVersion,
|
||||
);
|
||||
if (nodeType === undefined) {
|
||||
throw new ApplicationError('Node type is not known so cannot return parameter value', {
|
||||
tags: { nodeType: this.node.type },
|
||||
});
|
||||
}
|
||||
returnData = extractValue(
|
||||
returnData,
|
||||
parameterPath,
|
||||
this.node,
|
||||
nodeType,
|
||||
) as NodeParameterValueType;
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
getCurrentNodeParameters() {
|
||||
return this.additionalData.currentNodeParameters;
|
||||
}
|
||||
|
||||
// TODO: This is identical to PollContext
|
||||
getNodeParameter(
|
||||
parameterName: string,
|
||||
fallbackValue?: any,
|
||||
options?: IGetNodeParameterOptions,
|
||||
): NodeParameterValueType | object {
|
||||
const runExecutionData: IRunExecutionData | null = null;
|
||||
const itemIndex = 0;
|
||||
const runIndex = 0;
|
||||
const connectionInputData: INodeExecutionData[] = [];
|
||||
|
||||
return getNodeParameter(
|
||||
this.workflow,
|
||||
runExecutionData,
|
||||
runIndex,
|
||||
connectionInputData,
|
||||
this.node,
|
||||
parameterName,
|
||||
itemIndex,
|
||||
'internal',
|
||||
getAdditionalKeys(this.additionalData, 'internal', runExecutionData),
|
||||
undefined,
|
||||
fallbackValue,
|
||||
options,
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue