mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat: add workflow input mapping fields to resource mapper
This commit is contained in:
parent
8c38bf2d0a
commit
2dd4096800
|
@ -93,6 +93,26 @@ export class DynamicNodeParametersController {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/workflow-input-mapping-fields')
|
||||||
|
async getWorkflowInputMappingFields(
|
||||||
|
req: DynamicNodeParametersRequest.WorkflowInputMappingFields,
|
||||||
|
) {
|
||||||
|
const { path, methodName, credentials, currentNodeParameters, nodeTypeAndVersion } = req.body;
|
||||||
|
|
||||||
|
if (!methodName) throw new BadRequestError('Missing `methodName` in request body');
|
||||||
|
|
||||||
|
const additionalData = await getBase(req.user.id, currentNodeParameters);
|
||||||
|
|
||||||
|
return await this.service.getWorkflowInputMappingFields(
|
||||||
|
methodName,
|
||||||
|
path,
|
||||||
|
additionalData,
|
||||||
|
nodeTypeAndVersion,
|
||||||
|
currentNodeParameters,
|
||||||
|
credentials,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('/action-result')
|
@Post('/action-result')
|
||||||
async getActionResult(
|
async getActionResult(
|
||||||
req: DynamicNodeParametersRequest.ActionResult,
|
req: DynamicNodeParametersRequest.ActionResult,
|
||||||
|
|
|
@ -385,6 +385,11 @@ export declare namespace DynamicNodeParametersRequest {
|
||||||
methodName: string;
|
methodName: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
/** POST dynamic-node-parameters/workflow-input-mapping-fields */
|
||||||
|
type WorkflowInputMappingFields = BaseRequest<{
|
||||||
|
methodName: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
/** POST /dynamic-node-parameters/action-result */
|
/** POST /dynamic-node-parameters/action-result */
|
||||||
type ActionResult = BaseRequest<{
|
type ActionResult = BaseRequest<{
|
||||||
handler: string;
|
handler: string;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { LoadOptionsContext, NodeExecuteFunctions } from 'n8n-core';
|
import { LoadOptionsContext, NodeExecuteFunctions, WorkflowInputsContext } from 'n8n-core';
|
||||||
import type {
|
import type {
|
||||||
ILoadOptions,
|
ILoadOptions,
|
||||||
ILoadOptionsFunctions,
|
ILoadOptionsFunctions,
|
||||||
|
@ -17,12 +17,35 @@ import type {
|
||||||
INodeTypeNameVersion,
|
INodeTypeNameVersion,
|
||||||
NodeParameterValueType,
|
NodeParameterValueType,
|
||||||
IDataObject,
|
IDataObject,
|
||||||
|
IWorkflowInputsLoadOptionsFunctions,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { Workflow, RoutingNode, ApplicationError } from 'n8n-workflow';
|
import { Workflow, RoutingNode, ApplicationError } from 'n8n-workflow';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
|
|
||||||
import { NodeTypes } from '@/node-types';
|
import { NodeTypes } from '@/node-types';
|
||||||
|
|
||||||
|
type WorkflowInputsMappingMethod = (
|
||||||
|
this: IWorkflowInputsLoadOptionsFunctions,
|
||||||
|
) => Promise<ResourceMapperFields>;
|
||||||
|
type ListSearchMethod = (
|
||||||
|
this: ILoadOptionsFunctions,
|
||||||
|
filter?: string,
|
||||||
|
paginationToken?: string,
|
||||||
|
) => Promise<INodeListSearchResult>;
|
||||||
|
type LoadOptionsMethod = (this: ILoadOptionsFunctions) => Promise<INodePropertyOptions[]>;
|
||||||
|
type ActionHandlerMethod = (
|
||||||
|
this: ILoadOptionsFunctions,
|
||||||
|
payload?: string,
|
||||||
|
) => Promise<NodeParameterValueType>;
|
||||||
|
type ResourceMappingMethod = (this: ILoadOptionsFunctions) => Promise<ResourceMapperFields>;
|
||||||
|
|
||||||
|
type NodeMethod =
|
||||||
|
| WorkflowInputsMappingMethod
|
||||||
|
| ListSearchMethod
|
||||||
|
| LoadOptionsMethod
|
||||||
|
| ActionHandlerMethod
|
||||||
|
| ResourceMappingMethod;
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class DynamicNodeParametersService {
|
export class DynamicNodeParametersService {
|
||||||
constructor(private nodeTypes: NodeTypes) {}
|
constructor(private nodeTypes: NodeTypes) {}
|
||||||
|
@ -159,6 +182,23 @@ export class DynamicNodeParametersService {
|
||||||
return method.call(thisArgs);
|
return method.call(thisArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the available workflow input mapping fields for the ResourceMapper component */
|
||||||
|
async getWorkflowInputMappingFields(
|
||||||
|
methodName: string,
|
||||||
|
path: string,
|
||||||
|
additionalData: IWorkflowExecuteAdditionalData,
|
||||||
|
nodeTypeAndVersion: INodeTypeNameVersion,
|
||||||
|
currentNodeParameters: INodeParameters,
|
||||||
|
credentials?: INodeCredentials,
|
||||||
|
): Promise<ResourceMapperFields> {
|
||||||
|
const nodeType = this.getNodeType(nodeTypeAndVersion);
|
||||||
|
const method = this.getMethod('workflowInputsMapping', methodName, nodeType);
|
||||||
|
const workflow = this.getWorkflow(nodeTypeAndVersion, currentNodeParameters, credentials);
|
||||||
|
const thisArgs = this.getWorkflowInputsContext(path, additionalData, workflow);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
|
return method.call(thisArgs);
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the result of the action handler */
|
/** Returns the result of the action handler */
|
||||||
async getActionResult(
|
async getActionResult(
|
||||||
handler: string,
|
handler: string,
|
||||||
|
@ -181,33 +221,34 @@ export class DynamicNodeParametersService {
|
||||||
type: 'resourceMapping',
|
type: 'resourceMapping',
|
||||||
methodName: string,
|
methodName: string,
|
||||||
nodeType: INodeType,
|
nodeType: INodeType,
|
||||||
): (this: ILoadOptionsFunctions) => Promise<ResourceMapperFields>;
|
): ResourceMappingMethod;
|
||||||
private getMethod(
|
private getMethod(
|
||||||
type: 'listSearch',
|
type: 'workflowInputsMapping',
|
||||||
methodName: string,
|
methodName: string,
|
||||||
nodeType: INodeType,
|
nodeType: INodeType,
|
||||||
): (
|
): WorkflowInputsMappingMethod;
|
||||||
this: ILoadOptionsFunctions,
|
private getMethod(type: 'listSearch', methodName: string, nodeType: INodeType): ListSearchMethod;
|
||||||
filter?: string | undefined,
|
|
||||||
paginationToken?: string | undefined,
|
|
||||||
) => Promise<INodeListSearchResult>;
|
|
||||||
private getMethod(
|
private getMethod(
|
||||||
type: 'loadOptions',
|
type: 'loadOptions',
|
||||||
methodName: string,
|
methodName: string,
|
||||||
nodeType: INodeType,
|
nodeType: INodeType,
|
||||||
): (this: ILoadOptionsFunctions) => Promise<INodePropertyOptions[]>;
|
): LoadOptionsMethod;
|
||||||
private getMethod(
|
private getMethod(
|
||||||
type: 'actionHandler',
|
type: 'actionHandler',
|
||||||
methodName: string,
|
methodName: string,
|
||||||
nodeType: INodeType,
|
nodeType: INodeType,
|
||||||
): (this: ILoadOptionsFunctions, payload?: string) => Promise<NodeParameterValueType>;
|
): ActionHandlerMethod;
|
||||||
|
|
||||||
private getMethod(
|
private getMethod(
|
||||||
type: 'resourceMapping' | 'listSearch' | 'loadOptions' | 'actionHandler',
|
type:
|
||||||
|
| 'resourceMapping'
|
||||||
|
| 'workflowInputsMapping'
|
||||||
|
| 'listSearch'
|
||||||
|
| 'loadOptions'
|
||||||
|
| 'actionHandler',
|
||||||
methodName: string,
|
methodName: string,
|
||||||
nodeType: INodeType,
|
nodeType: INodeType,
|
||||||
) {
|
): NodeMethod {
|
||||||
const method = nodeType.methods?.[type]?.[methodName];
|
const method = nodeType.methods?.[type]?.[methodName] as NodeMethod;
|
||||||
if (typeof method !== 'function') {
|
if (typeof method !== 'function') {
|
||||||
throw new ApplicationError('Node type does not have method defined', {
|
throw new ApplicationError('Node type does not have method defined', {
|
||||||
tags: { nodeType: nodeType.description.name },
|
tags: { nodeType: nodeType.description.name },
|
||||||
|
@ -255,4 +296,13 @@ export class DynamicNodeParametersService {
|
||||||
const node = workflow.nodes['Temp-Node'];
|
const node = workflow.nodes['Temp-Node'];
|
||||||
return new LoadOptionsContext(workflow, node, additionalData, path);
|
return new LoadOptionsContext(workflow, node, additionalData, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getWorkflowInputsContext(
|
||||||
|
path: string,
|
||||||
|
additionalData: IWorkflowExecuteAdditionalData,
|
||||||
|
workflow: Workflow,
|
||||||
|
) {
|
||||||
|
const node = workflow.nodes['Temp-Node'];
|
||||||
|
return new WorkflowInputsContext(workflow, node, additionalData, path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ export { ExecuteContext } from './execute-context';
|
||||||
export { ExecuteSingleContext } from './execute-single-context';
|
export { ExecuteSingleContext } from './execute-single-context';
|
||||||
export { HookContext } from './hook-context';
|
export { HookContext } from './hook-context';
|
||||||
export { LoadOptionsContext } from './load-options-context';
|
export { LoadOptionsContext } from './load-options-context';
|
||||||
|
export { WorkflowInputsContext } from './workflow-inputs-context';
|
||||||
export { PollContext } from './poll-context';
|
export { PollContext } from './poll-context';
|
||||||
export { SupplyDataContext } from './supply-data-context';
|
export { SupplyDataContext } from './supply-data-context';
|
||||||
export { TriggerContext } from './trigger-context';
|
export { TriggerContext } from './trigger-context';
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { get } from 'lodash';
|
||||||
|
import { ApplicationError } from 'n8n-workflow';
|
||||||
|
import type {
|
||||||
|
INodeParameterResourceLocator,
|
||||||
|
IGetNodeParameterOptions,
|
||||||
|
INode,
|
||||||
|
IWorkflowExecuteAdditionalData,
|
||||||
|
NodeParameterValueType,
|
||||||
|
Workflow,
|
||||||
|
IWorkflowInputsLoadOptionsFunctions,
|
||||||
|
FieldType,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { extractValue } from '@/ExtractValue';
|
||||||
|
|
||||||
|
import { NodeExecutionContext } from './node-execution-context';
|
||||||
|
// eslint-disable-next-line import/no-cycle
|
||||||
|
|
||||||
|
export class WorkflowInputsContext
|
||||||
|
extends NodeExecutionContext
|
||||||
|
implements IWorkflowInputsLoadOptionsFunctions
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
workflow: Workflow,
|
||||||
|
node: INode,
|
||||||
|
additionalData: IWorkflowExecuteAdditionalData,
|
||||||
|
private readonly path: string,
|
||||||
|
) {
|
||||||
|
super(workflow, node, additionalData, 'internal');
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorkflowInputValues(): Array<{ name: string; type: FieldType }> {
|
||||||
|
const { value } = this.getCurrentNodeParameter('workflowId') as INodeParameterResourceLocator;
|
||||||
|
|
||||||
|
const workflowId = value as string;
|
||||||
|
if (!workflowId) {
|
||||||
|
throw new ApplicationError('No workflowId defined on node!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: load the inputs from the workflow
|
||||||
|
const dummyFields = [
|
||||||
|
{ name: 'field1', type: 'string' as const },
|
||||||
|
{ name: 'field2', type: 'number' as const },
|
||||||
|
{ name: 'field3', type: 'boolean' as const },
|
||||||
|
];
|
||||||
|
|
||||||
|
return dummyFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
returnData = extractValue(
|
||||||
|
returnData,
|
||||||
|
parameterPath,
|
||||||
|
this.node,
|
||||||
|
nodeType,
|
||||||
|
) as NodeParameterValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1275,6 +1275,10 @@ export declare namespace DynamicNodeParameters {
|
||||||
methodName: string;
|
methodName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WorkflowInputMappingFieldsRequest extends BaseRequest {
|
||||||
|
methodName: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface ActionResultRequest extends BaseRequest {
|
interface ActionResultRequest extends BaseRequest {
|
||||||
handler: string;
|
handler: string;
|
||||||
payload: IDataObject | string | undefined;
|
payload: IDataObject | string | undefined;
|
||||||
|
|
|
@ -59,6 +59,18 @@ export async function getResourceMapperFields(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getWorkflowInputFields(
|
||||||
|
context: IRestApiContext,
|
||||||
|
sendData: DynamicNodeParameters.WorkflowInputMappingFieldsRequest,
|
||||||
|
): Promise<ResourceMapperFields> {
|
||||||
|
return await makeRestApiRequest(
|
||||||
|
context,
|
||||||
|
'POST',
|
||||||
|
'/dynamic-node-parameters/workflow-input-mapping-fields',
|
||||||
|
sendData,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export async function getNodeParameterActionResult(
|
export async function getNodeParameterActionResult(
|
||||||
context: IRestApiContext,
|
context: IRestApiContext,
|
||||||
sendData: DynamicNodeParameters.ActionResultRequest,
|
sendData: DynamicNodeParameters.ActionResultRequest,
|
||||||
|
|
|
@ -244,11 +244,13 @@ async function loadFieldsToMap(): Promise<void> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const methodName = props.parameter.typeOptions?.resourceMapper?.resourceMapperMethod;
|
const resourceMapperMethod = props.parameter.typeOptions?.resourceMapper?.resourceMapperMethod;
|
||||||
if (typeof methodName !== 'string') {
|
const workflowInputsMappingMethod =
|
||||||
return;
|
props.parameter.typeOptions?.resourceMapper?.workflowInputsMappingMethod;
|
||||||
}
|
|
||||||
|
|
||||||
|
let fetchedFields = null;
|
||||||
|
|
||||||
|
if (typeof resourceMapperMethod === 'string') {
|
||||||
const requestParams: DynamicNodeParameters.ResourceMapperFieldsRequest = {
|
const requestParams: DynamicNodeParameters.ResourceMapperFieldsRequest = {
|
||||||
nodeTypeAndVersion: {
|
nodeTypeAndVersion: {
|
||||||
name: props.node?.type,
|
name: props.node?.type,
|
||||||
|
@ -259,10 +261,28 @@ async function loadFieldsToMap(): Promise<void> {
|
||||||
props.node.parameters,
|
props.node.parameters,
|
||||||
) as INodeParameters,
|
) as INodeParameters,
|
||||||
path: props.path,
|
path: props.path,
|
||||||
methodName,
|
methodName: resourceMapperMethod,
|
||||||
credentials: props.node.credentials,
|
credentials: props.node.credentials,
|
||||||
};
|
};
|
||||||
const fetchedFields = await nodeTypesStore.getResourceMapperFields(requestParams);
|
fetchedFields = await nodeTypesStore.getResourceMapperFields(requestParams);
|
||||||
|
} else {
|
||||||
|
if (typeof workflowInputsMappingMethod === 'string') {
|
||||||
|
const requestParams: DynamicNodeParameters.WorkflowInputMappingFieldsRequest = {
|
||||||
|
nodeTypeAndVersion: {
|
||||||
|
name: props.node?.type,
|
||||||
|
version: props.node.typeVersion,
|
||||||
|
},
|
||||||
|
currentNodeParameters: resolveRequiredParameters(
|
||||||
|
props.parameter,
|
||||||
|
props.node.parameters,
|
||||||
|
) as INodeParameters,
|
||||||
|
path: props.path,
|
||||||
|
methodName: workflowInputsMappingMethod,
|
||||||
|
};
|
||||||
|
fetchedFields = await nodeTypesStore.getWorkflowInputFields(requestParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fetchedFields !== null) {
|
if (fetchedFields !== null) {
|
||||||
const newSchema = fetchedFields.fields.map((field) => {
|
const newSchema = fetchedFields.fields.map((field) => {
|
||||||
const existingField = state.paramValue.schema.find((f) => f.id === field.id);
|
const existingField = state.paramValue.schema.find((f) => f.id === field.id);
|
||||||
|
|
|
@ -302,6 +302,16 @@ export const useNodeTypesStore = defineStore(STORES.NODE_TYPES, () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getWorkflowInputFields = async (
|
||||||
|
sendData: DynamicNodeParameters.WorkflowInputMappingFieldsRequest,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
return await nodeTypesApi.getWorkflowInputFields(rootStore.restApiContext, sendData);
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getNodeParameterActionResult = async (
|
const getNodeParameterActionResult = async (
|
||||||
sendData: DynamicNodeParameters.ActionResultRequest,
|
sendData: DynamicNodeParameters.ActionResultRequest,
|
||||||
) => {
|
) => {
|
||||||
|
@ -326,6 +336,7 @@ export const useNodeTypesStore = defineStore(STORES.NODE_TYPES, () => {
|
||||||
visibleNodeTypesByInputConnectionTypeNames,
|
visibleNodeTypesByInputConnectionTypeNames,
|
||||||
isConfigurableNode,
|
isConfigurableNode,
|
||||||
getResourceMapperFields,
|
getResourceMapperFields,
|
||||||
|
getWorkflowInputFields,
|
||||||
getNodeParameterActionResult,
|
getNodeParameterActionResult,
|
||||||
getResourceLocatorResults,
|
getResourceLocatorResults,
|
||||||
getNodeParameterOptions,
|
getNodeParameterOptions,
|
||||||
|
|
|
@ -199,9 +199,10 @@ export class ExecuteWorkflow implements INodeType {
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
typeOptions: {
|
typeOptions: {
|
||||||
loadOptionsDependsOn: ['workflowId.value', 'workflowJson'],
|
loadOptionsDependsOn: ['workflowId.value'],
|
||||||
resourceMapper: {
|
resourceMapper: {
|
||||||
resourceMapperMethod: 'getWorkflowInputs',
|
workflowInputsMappingMethod: 'getWorkflowInputs',
|
||||||
|
valuesLabel: 'Workflow Inputs',
|
||||||
mode: 'add',
|
mode: 'add',
|
||||||
fieldWords: {
|
fieldWords: {
|
||||||
singular: 'workflow input',
|
singular: 'workflow input',
|
||||||
|
@ -214,11 +215,11 @@ export class ExecuteWorkflow implements INodeType {
|
||||||
},
|
},
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
|
source: ['database'],
|
||||||
'@version': [{ _cnd: { gte: 1.2 } }],
|
'@version': [{ _cnd: { gte: 1.2 } }],
|
||||||
},
|
},
|
||||||
hide: {
|
hide: {
|
||||||
workflowId: [''],
|
workflowId: [''],
|
||||||
workflowJson: ['\n\n\n'],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -264,7 +265,7 @@ export class ExecuteWorkflow implements INodeType {
|
||||||
};
|
};
|
||||||
|
|
||||||
methods = {
|
methods = {
|
||||||
resourceMapping: {
|
workflowInputsMapping: {
|
||||||
getWorkflowInputs,
|
getWorkflowInputs,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,34 +1,14 @@
|
||||||
import type {
|
import type {
|
||||||
FieldType,
|
FieldType,
|
||||||
ILoadOptionsFunctions,
|
IWorkflowInputsLoadOptionsFunctions,
|
||||||
ResourceMapperField,
|
ResourceMapperField,
|
||||||
ResourceMapperFields,
|
ResourceMapperFields,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { getWorkflowInfo } from '../GenericFunctions';
|
|
||||||
|
|
||||||
export async function getWorkflowInputs(
|
export async function getWorkflowInputs(
|
||||||
this: ILoadOptionsFunctions,
|
this: IWorkflowInputsLoadOptionsFunctions,
|
||||||
): Promise<ResourceMapperFields> {
|
): Promise<ResourceMapperFields> {
|
||||||
const source = this.getNodeParameter('source', 0) as string;
|
const workflowInputs = this.getWorkflowInputValues() as Array<{ name: string; type: FieldType }>;
|
||||||
|
|
||||||
const executeWorkflowInfo = await getWorkflowInfo.call(this, source);
|
|
||||||
|
|
||||||
if (executeWorkflowInfo.code === undefined) {
|
|
||||||
// executeWorkflowInfo.code = await getWorkflowById.call(this, executeWorkflowInfo.id as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
const workflowInputs = (
|
|
||||||
Array.isArray(
|
|
||||||
executeWorkflowInfo.code?.nodes.find(
|
|
||||||
(node) => node.type === 'n8n-nodes-base.executeWorkflowTrigger',
|
|
||||||
)?.parameters.workflowInputs,
|
|
||||||
)
|
|
||||||
? executeWorkflowInfo.code?.nodes.find(
|
|
||||||
(node) => node.type === 'n8n-nodes-base.executeWorkflowTrigger',
|
|
||||||
)?.parameters.workflowInputs
|
|
||||||
: []
|
|
||||||
) as Array<{ name: string; type: FieldType }>;
|
|
||||||
|
|
||||||
const fields: ResourceMapperField[] = workflowInputs.map((currentWorkflowInput) => ({
|
const fields: ResourceMapperField[] = workflowInputs.map((currentWorkflowInput) => ({
|
||||||
id: currentWorkflowInput.name,
|
id: currentWorkflowInput.name,
|
||||||
|
@ -36,7 +16,7 @@ export async function getWorkflowInputs(
|
||||||
required: false,
|
required: false,
|
||||||
defaultMatch: true,
|
defaultMatch: true,
|
||||||
display: true,
|
display: true,
|
||||||
type: currentWorkflowInput.type || 'string',
|
type: currentWorkflowInput.type,
|
||||||
canBeUsedToMatch: true,
|
canBeUsedToMatch: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -95,10 +95,7 @@ function getFieldEntries(context: IExecuteFunctions): ValueOptions[] {
|
||||||
let result: ValueOptions[] | string = 'Internal Error: Invalid input source';
|
let result: ValueOptions[] | string = 'Internal Error: Invalid input source';
|
||||||
try {
|
try {
|
||||||
if (inputSource === WORKFLOW_INPUTS) {
|
if (inputSource === WORKFLOW_INPUTS) {
|
||||||
result = context.getNodeParameter(`${WORKFLOW_INPUTS}.${VALUES}`, 0, []) as Array<{
|
result = context.getNodeParameter(`${WORKFLOW_INPUTS}.${VALUES}`, 0, []) as ValueOptions[];
|
||||||
name: string;
|
|
||||||
type: FieldType;
|
|
||||||
}>;
|
|
||||||
} else if (inputSource === JSON_EXAMPLE) {
|
} else if (inputSource === JSON_EXAMPLE) {
|
||||||
const schema = parseJsonExample(context);
|
const schema = parseJsonExample(context);
|
||||||
result = parseJsonSchema(schema);
|
result = parseJsonSchema(schema);
|
||||||
|
|
|
@ -1070,6 +1070,10 @@ export interface ILoadOptionsFunctions extends FunctionsBase {
|
||||||
helpers: RequestHelperFunctions & SSHTunnelFunctions;
|
helpers: RequestHelperFunctions & SSHTunnelFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IWorkflowInputsLoadOptionsFunctions {
|
||||||
|
getWorkflowInputValues(): Array<{ name: string; type: FieldType }>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPollFunctions
|
export interface IPollFunctions
|
||||||
extends FunctionsBaseWithRequiredKeys<'getMode' | 'getActivationMode'> {
|
extends FunctionsBaseWithRequiredKeys<'getMode' | 'getActivationMode'> {
|
||||||
__emit(
|
__emit(
|
||||||
|
@ -1350,11 +1354,13 @@ export interface INodePropertyTypeOptions {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResourceMapperTypeOptions {
|
export interface ResourceMapperTypeOptionsBase {
|
||||||
resourceMapperMethod: string;
|
|
||||||
mode: 'add' | 'update' | 'upsert';
|
mode: 'add' | 'update' | 'upsert';
|
||||||
valuesLabel?: string;
|
valuesLabel?: string;
|
||||||
fieldWords?: { singular: string; plural: string };
|
fieldWords?: {
|
||||||
|
singular: string;
|
||||||
|
plural: string;
|
||||||
|
};
|
||||||
addAllFields?: boolean;
|
addAllFields?: boolean;
|
||||||
noFieldsError?: string;
|
noFieldsError?: string;
|
||||||
multiKeyMatch?: boolean;
|
multiKeyMatch?: boolean;
|
||||||
|
@ -1366,6 +1372,17 @@ export interface ResourceMapperTypeOptions {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enforce at least one of resourceMapperMethod or workflowInputsMappingMethod
|
||||||
|
export type ResourceMapperTypeOptions =
|
||||||
|
| (ResourceMapperTypeOptionsBase & {
|
||||||
|
resourceMapperMethod: string;
|
||||||
|
workflowInputsMappingMethod?: never;
|
||||||
|
})
|
||||||
|
| (ResourceMapperTypeOptionsBase & {
|
||||||
|
workflowInputsMappingMethod: string;
|
||||||
|
resourceMapperMethod?: never;
|
||||||
|
});
|
||||||
|
|
||||||
type NonEmptyArray<T> = [T, ...T[]];
|
type NonEmptyArray<T> = [T, ...T[]];
|
||||||
|
|
||||||
export type FilterTypeCombinator = 'and' | 'or';
|
export type FilterTypeCombinator = 'and' | 'or';
|
||||||
|
@ -1628,6 +1645,11 @@ export interface INodeType {
|
||||||
resourceMapping?: {
|
resourceMapping?: {
|
||||||
[functionName: string]: (this: ILoadOptionsFunctions) => Promise<ResourceMapperFields>;
|
[functionName: string]: (this: ILoadOptionsFunctions) => Promise<ResourceMapperFields>;
|
||||||
};
|
};
|
||||||
|
workflowInputsMapping?: {
|
||||||
|
[functionName: string]: (
|
||||||
|
this: IWorkflowInputsLoadOptionsFunctions,
|
||||||
|
) => Promise<ResourceMapperFields>;
|
||||||
|
};
|
||||||
actionHandler?: {
|
actionHandler?: {
|
||||||
[functionName: string]: (
|
[functionName: string]: (
|
||||||
this: ILoadOptionsFunctions,
|
this: ILoadOptionsFunctions,
|
||||||
|
|
Loading…
Reference in a new issue