diff --git a/packages/editor-ui/src/components/ParameterInputWrapper.vue b/packages/editor-ui/src/components/ParameterInputWrapper.vue index 957b21a9ac..a3c9c558a4 100644 --- a/packages/editor-ui/src/components/ParameterInputWrapper.vue +++ b/packages/editor-ui/src/components/ParameterInputWrapper.vue @@ -202,14 +202,18 @@ export default defineComponent({ ? this.modelValue.value : this.modelValue; - if (!this.activeNode || !this.isValueExpression || typeof value !== 'string') { + if ( + !this.isForCredential && + (!this.activeNode || !this.isValueExpression || typeof value !== 'string') + ) { return { ok: false, error: new Error() }; } try { - let opts; + let opts = { isForCredential: this.isForCredential }; if (this.ndvStore.isInputParentOfActiveNode) { opts = { + ...opts, targetItem: this.targetItem ?? undefined, inputNodeName: this.ndvStore.ndvInputNodeName, inputRunIndex: this.ndvStore.ndvInputRunIndex, diff --git a/packages/editor-ui/src/composables/useWorkflowHelpers.ts b/packages/editor-ui/src/composables/useWorkflowHelpers.ts index e6b452abbc..9a44f5bb87 100644 --- a/packages/editor-ui/src/composables/useWorkflowHelpers.ts +++ b/packages/editor-ui/src/composables/useWorkflowHelpers.ts @@ -82,16 +82,51 @@ export function resolveParameter( inputRunIndex?: number; inputBranchIndex?: number; additionalKeys?: IWorkflowDataProxyAdditionalKeys; + isForCredential?: boolean; } = {}, ): IDataObject | null { let itemIndex = opts?.targetItem?.itemIndex || 0; + const workflow = getCurrentWorkflow(); + + const additionalKeys: IWorkflowDataProxyAdditionalKeys = { + $execution: { + id: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, + mode: 'test', + resumeUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, + resumeFormUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, + }, + $vars: useEnvironmentsStore().variablesAsObject, + + // deprecated + $executionId: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, + $resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, + + ...opts.additionalKeys, + }; + + if (opts.isForCredential) { + // node-less expression resolution + return workflow.expression.getParameterValue( + parameter, + null, + 0, + itemIndex, + '', + [], + 'manual', + additionalKeys, + undefined, + false, + undefined, + '', + ) as IDataObject; + } + const inputName = NodeConnectionType.Main; const activeNode = useNDVStore().activeNode; let contextNode = activeNode; - const workflow = getCurrentWorkflow(); - if (activeNode) { contextNode = workflow.getParentMainInputNode(activeNode); } @@ -159,22 +194,6 @@ export function resolveParameter( _connectionInputData = []; } - const additionalKeys: IWorkflowDataProxyAdditionalKeys = { - $execution: { - id: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, - mode: 'test', - resumeUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, - resumeFormUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, - }, - $vars: useEnvironmentsStore().variablesAsObject, - - // deprecated - $executionId: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, - $resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, - - ...opts.additionalKeys, - }; - if (activeNode?.type === HTTP_REQUEST_NODE_TYPE) { const EMPTY_RESPONSE = { statusCode: 200, headers: {}, body: {} }; const EMPTY_REQUEST = { headers: {}, body: {}, qs: {} }; @@ -793,6 +812,7 @@ export function useWorkflowHelpers(options: { router: ReturnType; @@ -123,11 +125,16 @@ export default defineComponent({ }); }, async initialize() { + const isVarsEnabled = useSettingsStore().isEnterpriseFeatureEnabled( + EnterpriseEditionFeature.Variables, + ); + const loadPromises = [ this.credentialsStore.fetchAllCredentials(), this.credentialsStore.fetchCredentialTypes(false), this.externalSecretsStore.fetchAllSecrets(), this.nodeTypesStore.loadNodeTypesIfNotLoaded(), + isVarsEnabled ? useEnvironmentsStore().fetchAllVariables() : Promise.resolve(), // for expression resolution ]; await Promise.all(loadPromises); diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 5cc245f330..e8a1091783 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -164,7 +164,9 @@ export class WorkflowDataProxy { const that = this; const node = this.workflow.nodes[nodeName]; - return new Proxy(node.parameters, { + // `node` is `undefined` only in expressions in credentials + + return new Proxy(node?.parameters ?? {}, { has: () => true, ownKeys(target) { return Reflect.ownKeys(target);