diff --git a/packages/core/src/ExtractValue.ts b/packages/core/src/ExtractValue.ts deleted file mode 100644 index ffd31aee30..0000000000 --- a/packages/core/src/ExtractValue.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { - INode, - INodeParameters, - INodeProperties, - INodePropertyCollection, - INodePropertyOptions, - INodeType, - NodeOperationError, - NodeParameterValueType, - NodeHelpers, - LoggerProxy, -} from 'n8n-workflow'; - -function findPropertyFromParameterName( - parameterName: string, - nodeType: INodeType, - node: INode, - nodeParameters: INodeParameters, -): INodePropertyOptions | INodeProperties | INodePropertyCollection { - let property: INodePropertyOptions | INodeProperties | INodePropertyCollection | undefined; - const paramParts = parameterName.split('.'); - let currentParamPath = ''; - - const findProp = ( - name: string, - options: Array, - ): INodePropertyOptions | INodeProperties | INodePropertyCollection | undefined => { - return options.find( - (i) => - i.name === name && - NodeHelpers.displayParameterPath(nodeParameters, i, currentParamPath, node), - ); - }; - - // eslint-disable-next-line no-restricted-syntax - for (const p of paramParts) { - const param = p.split('[')[0]; - if (!property) { - property = findProp(param, nodeType.description.properties); - } else if ('options' in property && property.options) { - property = findProp(param, property.options); - currentParamPath += `.${param}`; - } else if ('values' in property) { - property = findProp(param, property.values); - currentParamPath += `.${param}`; - } else { - throw new Error(`Couldn't not find property "${parameterName}"`); - } - if (!property) { - throw new Error(`Couldn't not find property "${parameterName}"`); - } - } - if (!property) { - throw new Error(`Couldn't not find property "${parameterName}"`); - } - - return property; -} - -function executeRegexExtractValue( - value: string, - regex: RegExp, - parameterName: string, - parameterDisplayName: string, -): NodeParameterValueType | object { - const extracted = regex.exec(value); - if (!extracted) { - throw new Error( - `ERROR: ${parameterDisplayName} parameter's value is invalid. This is likely because the URL entered is incorrect`, - ); - } - if (extracted.length < 2 || extracted.length > 2) { - throw new Error( - `Property "${parameterName}" has an invalid extractValue regex "${regex.source}". extractValue expects exactly one group to be returned.`, - ); - } - return extracted[1]; -} - -function extractValueRLC( - value: NodeParameterValueType | object, - property: INodeProperties, - parameterName: string, -): NodeParameterValueType | object { - // Not an RLC value - if (typeof value !== 'object' || !value || !('mode' in value) || !('value' in value)) { - return value; - } - const modeProp = (property.modes ?? []).find((i) => i.name === value.mode); - if (!modeProp) { - return value.value; - } - if (!('extractValue' in modeProp) || !modeProp.extractValue) { - return value.value; - } - - if (typeof value.value !== 'string') { - let typeName: string | undefined = value.value?.constructor.name; - if (value.value === null) { - typeName = 'null'; - } else if (typeName === undefined) { - typeName = 'undefined'; - } - LoggerProxy.error( - `Only strings can be passed to extractValue. Parameter "${parameterName}" passed "${typeName}"`, - ); - throw new Error( - `ERROR: ${property.displayName} parameter's value is invalid. Please enter a valid ${modeProp.displayName}.`, - ); - } - - if (modeProp.extractValue.type !== 'regex') { - throw new Error( - `Property "${parameterName}" has an unknown extractValue type "${ - modeProp.extractValue.type as string - }"`, - ); - } - - const regex = new RegExp(modeProp.extractValue.regex); - return executeRegexExtractValue(value.value, regex, parameterName, property.displayName); -} - -function extractValueOther( - value: NodeParameterValueType | object, - property: INodeProperties | INodePropertyCollection, - parameterName: string, -): NodeParameterValueType | object { - if (!('extractValue' in property) || !property.extractValue) { - return value; - } - - if (typeof value !== 'string') { - let typeName: string | undefined = value?.constructor.name; - if (value === null) { - typeName = 'null'; - } else if (typeName === undefined) { - typeName = 'undefined'; - } - LoggerProxy.error( - `Only strings can be passed to extractValue. Parameter "${parameterName}" passed "${typeName}"`, - ); - throw new Error( - `ERROR: ${property.displayName} parameter's value is invalid. Please enter a valid value.`, - ); - } - - if (property.extractValue.type !== 'regex') { - throw new Error( - `Property "${parameterName}" has an unknown extractValue type "${ - property.extractValue.type as string - }"`, - ); - } - - const regex = new RegExp(property.extractValue.regex); - return executeRegexExtractValue(value, regex, parameterName, property.displayName); -} - -export function extractValue( - value: NodeParameterValueType | object, - parameterName: string, - node: INode, - nodeType: INodeType, -): NodeParameterValueType | object { - let property: INodePropertyOptions | INodeProperties | INodePropertyCollection; - try { - property = findPropertyFromParameterName(parameterName, nodeType, node, node.parameters); - - // Definitely doesn't have value extractor - if (!('type' in property)) { - return value; - } - - if (property.type === 'resourceLocator') { - return extractValueRLC(value, property, parameterName); - } - return extractValueOther(value, property, parameterName); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - throw new NodeOperationError(node, error); - } -} diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 75b50dafcc..ec4d15f62a 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -59,7 +59,6 @@ import { LoggerProxy as Logger, IExecuteData, OAuth2GrantType, - IGetNodeParameterOptions, NodeParameterValueType, NodeExecutionWithMetadata, IPairedItemData, @@ -100,7 +99,6 @@ import { IWorkflowSettings, PLACEHOLDER_EMPTY_EXECUTION_ID, } from '.'; -import { extractValue } from './ExtractValue'; axios.defaults.timeout = 300000; // Prevent axios from adding x-form-www-urlencoded headers by default @@ -1727,7 +1725,6 @@ export function getNodeParameter( additionalKeys: IWorkflowDataProxyAdditionalKeys, executeData?: IExecuteData, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object { const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion); if (nodeType === undefined) { @@ -1762,11 +1759,6 @@ export function getNodeParameter( throw e; } - // This is outside the try/catch because it throws errors with proper messages - if (options?.extractValue) { - returnData = extractValue(returnData, parameterName, node, nodeType); - } - return returnData; } @@ -1939,7 +1931,6 @@ export function getExecutePollFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -1959,7 +1950,6 @@ export function getExecutePollFunctions( getAdditionalKeys(additionalData), undefined, fallbackValue, - options, ); }, getRestApiUrl: (): string => { @@ -2094,7 +2084,6 @@ export function getExecuteTriggerFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2114,7 +2103,6 @@ export function getExecuteTriggerFunctions( getAdditionalKeys(additionalData), undefined, fallbackValue, - options, ); }, getRestApiUrl: (): string => { @@ -2314,7 +2302,6 @@ export function getExecuteFunctions( parameterName: string, itemIndex: number, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { return getNodeParameter( workflow, @@ -2329,7 +2316,6 @@ export function getExecuteFunctions( getAdditionalKeys(additionalData), executeData, fallbackValue, - options, ); }, getMode: (): WorkflowExecuteMode => { @@ -2589,7 +2575,6 @@ export function getExecuteSingleFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { return getNodeParameter( workflow, @@ -2604,7 +2589,6 @@ export function getExecuteSingleFunctions( getAdditionalKeys(additionalData), executeData, fallbackValue, - options, ); }, getWorkflow: () => { @@ -2758,7 +2742,6 @@ export function getLoadOptionsFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2778,7 +2761,6 @@ export function getLoadOptionsFunctions( getAdditionalKeys(additionalData), undefined, fallbackValue, - options, ); }, getTimezone: (): string => { @@ -2886,7 +2868,6 @@ export function getExecuteHookFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2906,7 +2887,6 @@ export function getExecuteHookFunctions( getAdditionalKeys(additionalData), undefined, fallbackValue, - options, ); }, getNodeWebhookUrl: (name: string): string | undefined => { @@ -3046,7 +3026,6 @@ export function getExecuteWebhookFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -3066,7 +3045,6 @@ export function getExecuteWebhookFunctions( getAdditionalKeys(additionalData), undefined, fallbackValue, - options, ); }, getParamsData(): object { diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 392f15f0dc..c7ae83bf21 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -2,7 +2,7 @@
1) { @@ -165,14 +165,14 @@ export default mixins( parameterData = { node: this.node.name, name: this.path, - value: { value: updatedValue, mode: mode ? mode.name : '' }, + value: { __rl: true, value: updatedValue, mode: mode ? mode.name : '' }, }; } else { parameterData = { node: this.node.name, name: this.path, - value: { value: updatedValue, mode: this.value.mode }, + value: { __rl: true, value: updatedValue, mode: this.value.mode }, }; } diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index 7a30c3bec3..af9b4afc9e 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -174,6 +174,7 @@ import { workflowHelpers } from '../mixins/workflowHelpers'; import { nodeHelpers } from '../mixins/nodeHelpers'; import { getAppNameFromNodeName } from '../helpers'; import { type } from 'os'; +import { isResourceLocatorValue } from '@/typeGuards'; interface IResourceLocatorQuery { results: INodeListSearchItems[]; @@ -199,10 +200,6 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({ value: { type: [Object, String] as PropType, }, - mode: { - type: String, - default: '', - }, inputSize: { type: String, default: 'small', @@ -423,6 +420,11 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({ this.switchFromListMode(); } }, + currentMode(mode: INodePropertyMode) { + if (mode.extractValue && mode.extractValue.regex && isResourceLocatorValue(this.value) && this.value.__regex !== mode.extractValue.regex) { + this.$emit('input', {...this.value, __regex: mode.extractValue.regex}); + } + }, }, mounted() { this.$on('refreshList', this.refreshList); @@ -505,7 +507,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({ return null; }, onInputChange(value: string): void { - const params: INodeParameterResourceLocator = { value, mode: this.selectedMode }; + const params: INodeParameterResourceLocator = { __rl: true, value, mode: this.selectedMode }; if (this.isListMode) { const resource = this.currentQueryResults.find((resource) => resource.value === value); if (resource && resource.name) { @@ -520,13 +522,13 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({ }, onModeSelected(value: string): void { if (typeof this.value !== 'object') { - this.$emit('input', { value: this.value, mode: value }); + this.$emit('input', { __rl: true, value: this.value, mode: value }); } else if (value === 'url' && this.value && this.value.cachedResultUrl) { - this.$emit('input', { mode: value, value: this.value.cachedResultUrl }); + this.$emit('input', { __rl: true, mode: value, value: this.value.cachedResultUrl }); } else if (value === 'id' && this.selectedMode === 'list' && this.value && this.value.value) { - this.$emit('input', { mode: value, value: this.value.value }); + this.$emit('input', { __rl: true, mode: value, value: this.value.value }); } else { - this.$emit('input', { mode: value, value: '' }); + this.$emit('input', { __rl: true, mode: value, value: '' }); } this.trackEvent('User changed resource locator mode', { mode: value }); @@ -657,7 +659,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({ } if (mode) { - this.$emit('input', { value: ((this.value && typeof this.value === 'object')? this.value.value: ''), mode: mode.name }); + this.$emit('input', { __rl: true, value: ((this.value && typeof this.value === 'object')? this.value.value: ''), mode: mode.name }); } } }, diff --git a/packages/editor-ui/src/typeGuards.ts b/packages/editor-ui/src/typeGuards.ts index 2818cc871b..73462eeeb8 100644 --- a/packages/editor-ui/src/typeGuards.ts +++ b/packages/editor-ui/src/typeGuards.ts @@ -1,5 +1,5 @@ import { INodeParameterResourceLocator } from "n8n-workflow"; export function isResourceLocatorValue(value: unknown): value is INodeParameterResourceLocator { - return Boolean(typeof value === 'object' && value && 'mode' in value && 'mode' in value); + return Boolean(typeof value === 'object' && value && 'mode' in value && 'value' in value); } diff --git a/packages/nodes-base/nodes/Airtable/Airtable.node.ts b/packages/nodes-base/nodes/Airtable/Airtable.node.ts index 4ae888f4e1..1d72396f27 100644 --- a/packages/nodes-base/nodes/Airtable/Airtable.node.ts +++ b/packages/nodes-base/nodes/Airtable/Airtable.node.ts @@ -508,15 +508,8 @@ export class Airtable implements INodeType { const operation = this.getNodeParameter('operation', 0) as string; - const application = this.getNodeParameter('application', 0, undefined, { - extractValue: true, - }) as string; - - const table = encodeURI( - this.getNodeParameter('table', 0, undefined, { - extractValue: true, - }) as string, - ); + const application = this.getNodeParameter('application', 0) as string; + const table = encodeURI(this.getNodeParameter('table', 0) as string); let returnAll = false; let endpoint = ''; diff --git a/packages/nodes-base/nodes/Google/Drive/GoogleDrive.node.ts b/packages/nodes-base/nodes/Google/Drive/GoogleDrive.node.ts index 0d5eb544f4..178cebd4a9 100644 --- a/packages/nodes-base/nodes/Google/Drive/GoogleDrive.node.ts +++ b/packages/nodes-base/nodes/Google/Drive/GoogleDrive.node.ts @@ -2153,9 +2153,7 @@ export class GoogleDrive implements INodeType { // delete // ---------------------------------- - const driveId = this.getNodeParameter('driveId', i, undefined, { - extractValue: true, - }) as string; + const driveId = this.getNodeParameter('driveId', i) as string; await googleApiRequest.call(this, 'DELETE', `/drive/v3/drives/${driveId}`); @@ -2171,9 +2169,7 @@ export class GoogleDrive implements INodeType { // get // ---------------------------------- - const driveId = this.getNodeParameter('driveId', i, undefined, { - extractValue: true, - }) as string; + const driveId = this.getNodeParameter('driveId', i) as string; const qs: IDataObject = {}; @@ -2233,9 +2229,7 @@ export class GoogleDrive implements INodeType { // update // ---------------------------------- - const driveId = this.getNodeParameter('driveId', i, undefined, { - extractValue: true, - }) as string; + const driveId = this.getNodeParameter('driveId', i) as string; const body: IDataObject = {}; @@ -2262,9 +2256,7 @@ export class GoogleDrive implements INodeType { // copy // ---------------------------------- - const fileId = this.getNodeParameter('fileId', i, undefined, { - extractValue: true, - }) as string; + const fileId = this.getNodeParameter('fileId', i) as string; const body: IDataObject = { fields: queryFields, @@ -2300,9 +2292,7 @@ export class GoogleDrive implements INodeType { // download // ---------------------------------- - const fileId = this.getNodeParameter('fileId', i, undefined, { - extractValue: true, - }) as string; + const fileId = this.getNodeParameter('fileId', i) as string; const options = this.getNodeParameter('options', i) as IDataObject; const requestOptions = { @@ -2645,9 +2635,7 @@ export class GoogleDrive implements INodeType { // file:update // ---------------------------------- - const id = this.getNodeParameter('fileId', i, undefined, { - extractValue: true, - }) as string; + const id = this.getNodeParameter('fileId', i) as string; const updateFields = this.getNodeParameter('updateFields', i, {}) as IDataObject; const qs: IDataObject = { @@ -2721,9 +2709,7 @@ export class GoogleDrive implements INodeType { // delete // ---------------------------------- - const fileId = this.getNodeParameter('fileId', i, undefined, { - extractValue: true, - }) as string; + const fileId = this.getNodeParameter('fileId', i) as string; await googleApiRequest.call( this, @@ -2745,9 +2731,7 @@ export class GoogleDrive implements INodeType { returnData.push(...executionData); } if (operation === 'share') { - const fileId = this.getNodeParameter('fileId', i, undefined, { - extractValue: true, - }) as string; + const fileId = this.getNodeParameter('fileId', i) as string; const permissions = this.getNodeParameter('permissionsUi', i) as IDataObject; diff --git a/packages/nodes-base/nodes/Trello/Trello.node.ts b/packages/nodes-base/nodes/Trello/Trello.node.ts index ad1050adfe..0966bc15a9 100644 --- a/packages/nodes-base/nodes/Trello/Trello.node.ts +++ b/packages/nodes-base/nodes/Trello/Trello.node.ts @@ -239,9 +239,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const id = this.getNodeParameter('id', i, undefined, { - extractValue: true, - }) as string; + const id = this.getNodeParameter('id', i) as string; endpoint = `boards/${id}`; } else if (operation === 'get') { @@ -251,7 +249,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const id = this.getNodeParameter('id', i, undefined, { extractValue: true }); + const id = this.getNodeParameter('id', i); endpoint = `boards/${id}`; @@ -264,7 +262,7 @@ export class Trello implements INodeType { requestMethod = 'PUT'; - const id = this.getNodeParameter('id', i, undefined, { extractValue: true }); + const id = this.getNodeParameter('id', i); endpoint = `boards/${id}`; @@ -367,7 +365,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const id = this.getNodeParameter('id', i, undefined, { extractValue: true }); + const id = this.getNodeParameter('id', i); endpoint = `cards/${id}`; } else if (operation === 'get') { @@ -377,7 +375,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const id = this.getNodeParameter('id', i, undefined, { extractValue: true }); + const id = this.getNodeParameter('id', i); endpoint = `cards/${id}`; @@ -390,7 +388,7 @@ export class Trello implements INodeType { requestMethod = 'PUT'; - const id = this.getNodeParameter('id', i, undefined, { extractValue: true }); + const id = this.getNodeParameter('id', i); endpoint = `cards/${id}`; @@ -409,9 +407,7 @@ export class Trello implements INodeType { // create // ---------------------------------- - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; qs.text = this.getNodeParameter('text', i) as string; @@ -425,9 +421,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const commentId = this.getNodeParameter('commentId', i) as string; @@ -439,9 +433,7 @@ export class Trello implements INodeType { requestMethod = 'PUT'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const commentId = this.getNodeParameter('commentId', i) as string; @@ -560,9 +552,7 @@ export class Trello implements INodeType { requestMethod = 'POST'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const url = this.getNodeParameter('url', i) as string; @@ -581,9 +571,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const id = this.getNodeParameter('id', i) as string; @@ -595,9 +583,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const id = this.getNodeParameter('id', i) as string; @@ -612,9 +598,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; endpoint = `cards/${cardId}/attachments`; @@ -635,9 +619,7 @@ export class Trello implements INodeType { requestMethod = 'POST'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const name = this.getNodeParameter('name', i) as string; @@ -654,9 +636,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const id = this.getNodeParameter('id', i) as string; @@ -681,9 +661,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; endpoint = `cards/${cardId}/checklists`; @@ -696,9 +674,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const checkItemId = this.getNodeParameter('checkItemId', i) as string; @@ -727,9 +703,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const checkItemId = this.getNodeParameter('checkItemId', i) as string; @@ -741,9 +715,7 @@ export class Trello implements INodeType { requestMethod = 'PUT'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const checkItemId = this.getNodeParameter('checkItemId', i) as string; @@ -758,9 +730,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; endpoint = `cards/${cardId}/checkItemStates`; @@ -781,9 +751,7 @@ export class Trello implements INodeType { requestMethod = 'POST'; - const idBoard = this.getNodeParameter('boardId', i, undefined, { - extractValue: true, - }) as string; + const idBoard = this.getNodeParameter('boardId', i) as string; const name = this.getNodeParameter('name', i) as string; const color = this.getNodeParameter('color', i) as string; @@ -825,9 +793,7 @@ export class Trello implements INodeType { requestMethod = 'GET'; - const idBoard = this.getNodeParameter('boardId', i, undefined, { - extractValue: true, - }) as string; + const idBoard = this.getNodeParameter('boardId', i) as string; endpoint = `board/${idBoard}/labels`; @@ -854,9 +820,7 @@ export class Trello implements INodeType { requestMethod = 'POST'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const id = this.getNodeParameter('id', i) as string; @@ -870,9 +834,7 @@ export class Trello implements INodeType { requestMethod = 'DELETE'; - const cardId = this.getNodeParameter('cardId', i, undefined, { - extractValue: true, - }) as string; + const cardId = this.getNodeParameter('cardId', i) as string; const id = this.getNodeParameter('id', i) as string; diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 6241e0f692..e5da2277f0 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -543,10 +543,6 @@ export interface IN8nRequestOperationPaginationOffset extends IN8nRequestOperati }; } -export interface IGetNodeParameterOptions { - extractValue?: boolean; -} - export interface IExecuteFunctions { continueOnFail(): boolean; evaluateExpression(expression: string, itemIndex: number): NodeParameterValueType; @@ -568,7 +564,6 @@ export interface IExecuteFunctions { parameterName: string, itemIndex: number, fallbackValue?: any, - options?: IGetNodeParameterOptions, ): NodeParameterValueType | object; getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData; getWorkflowStaticData(type: string): IDataObject; @@ -606,11 +601,7 @@ export interface IExecuteSingleFunctions { getItemIndex(): number; getMode(): WorkflowExecuteMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - options?: IGetNodeParameterOptions, - ): NodeParameterValueType | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getRestApiUrl(): string; getTimezone(): string; getExecuteData(): IExecuteData; @@ -656,11 +647,7 @@ export interface ICredentialTestFunctions { export interface ILoadOptionsFunctions { getCredentials(type: string): Promise; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - options?: IGetNodeParameterOptions, - ): NodeParameterValueType | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getCurrentNodeParameter(parameterName: string): NodeParameterValueType | object | undefined; getCurrentNodeParameters(): INodeParameters | undefined; getTimezone(): string; @@ -693,11 +680,7 @@ export interface IHookFunctions { getActivationMode(): WorkflowActivateMode; getNode(): INode; getNodeWebhookUrl: (name: string) => string | undefined; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - options?: IGetNodeParameterOptions, - ): NodeParameterValueType | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getTimezone(): string; getWebhookDescription(name: string): IWebhookDescription | undefined; getWebhookName(): string; @@ -723,11 +706,7 @@ export interface IPollFunctions { getMode(): WorkflowExecuteMode; getActivationMode(): WorkflowActivateMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - options?: IGetNodeParameterOptions, - ): NodeParameterValueType | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getRestApiUrl(): string; getTimezone(): string; getWorkflow(): IWorkflowMetadata; @@ -757,11 +736,7 @@ export interface ITriggerFunctions { getMode(): WorkflowExecuteMode; getActivationMode(): WorkflowActivateMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - options?: IGetNodeParameterOptions, - ): NodeParameterValueType | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getRestApiUrl(): string; getTimezone(): string; getWorkflow(): IWorkflowMetadata; @@ -786,11 +761,7 @@ export interface IWebhookFunctions { getHeaderData(): object; getMode(): WorkflowExecuteMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - options?: IGetNodeParameterOptions, - ): NodeParameterValueType | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getNodeWebhookUrl: (name: string) => string | undefined; getParamsData(): object; getQueryData(): object; @@ -905,10 +876,12 @@ export interface IResourceLocatorResult { } export interface INodeParameterResourceLocator { + __rl: true; mode: ResourceLocatorModes; value: NodeParameterValue; cachedResultName?: string; cachedResultUrl?: string; + __regex?: string; } export type NodeParameterValueType = diff --git a/packages/workflow/src/RoutingNode.ts b/packages/workflow/src/RoutingNode.ts index 6cbc35ef20..0973d3f377 100644 --- a/packages/workflow/src/RoutingNode.ts +++ b/packages/workflow/src/RoutingNode.ts @@ -643,15 +643,8 @@ export class RoutingNode { if (nodeProperties.routing) { let parameterValue: string | undefined; if (basePath + nodeProperties.name && 'type' in nodeProperties) { - // Extract value if it has extractValue defined or if it's a - // resourceLocator component. Resource locators are likely to have extractors - // and we can't know if the mode has one unless we dig all the way in. - const shouldExtractValue = - nodeProperties.extractValue !== undefined || nodeProperties.type === 'resourceLocator'; parameterValue = executeSingleFunctions.getNodeParameter( basePath + nodeProperties.name, - undefined, - { extractValue: shouldExtractValue }, ) as string; } diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 29c4a0e351..016505eb22 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -23,12 +23,19 @@ import { ITaskData, IWorkflowDataProxyAdditionalKeys, IWorkflowDataProxyData, + INodeParameterResourceLocator, NodeHelpers, NodeParameterValueType, Workflow, WorkflowExecuteMode, } from '.'; +export function isResourceLocatorValue(value: unknown): value is INodeParameterResourceLocator { + return Boolean( + typeof value === 'object' && value && 'mode' in value && 'value' in value && '__rl' in value, + ); +} + export class WorkflowDataProxy { private workflow: Workflow; @@ -194,6 +201,20 @@ export class WorkflowDataProxy { returnValue = node.parameters[name]; } + if (isResourceLocatorValue(returnValue)) { + if (returnValue.__regex && typeof returnValue.value === 'string') { + const expr = new RegExp(returnValue.__regex); + const extracted = expr.exec(returnValue.value); + if (extracted && extracted.length >= 2) { + returnValue = extracted[1]; + } else { + return returnValue.value; + } + } else { + returnValue = returnValue.value; + } + } + if (typeof returnValue === 'string' && returnValue.charAt(0) === '=') { // The found value is an expression so resolve it return that.workflow.expression.getParameterValue(