import { NodeConnectionType, type INodeProperties } from 'n8n-workflow'; export const metadataFilterField: INodeProperties = { displayName: 'Metadata Filter', name: 'metadata', type: 'fixedCollection', description: 'Metadata to filter the document by', typeOptions: { multipleValues: true, }, default: {}, placeholder: 'Add filter field', options: [ { name: 'metadataValues', displayName: 'Fields to Set', values: [ { displayName: 'Name', name: 'name', type: 'string', default: '', required: true, }, { displayName: 'Value', name: 'value', type: 'string', default: '', }, ], }, ], }; export function getTemplateNoticeField(templateId: number): INodeProperties { return { displayName: `Save time with an example of how this node works`, name: 'notice', type: 'notice', default: '', }; } const connectionsString = { [NodeConnectionType.AiAgent]: { // Root AI view connection: '', locale: 'AI Agent', }, [NodeConnectionType.AiChain]: { // Root AI view connection: '', locale: 'AI Chain', }, [NodeConnectionType.AiDocument]: { connection: NodeConnectionType.AiDocument, locale: 'Document Loader', }, [NodeConnectionType.AiVectorStore]: { connection: NodeConnectionType.AiVectorStore, locale: 'Vector Store', }, [NodeConnectionType.AiRetriever]: { connection: NodeConnectionType.AiRetriever, locale: 'Vector Store Retriever', }, }; type AllowedConnectionTypes = | NodeConnectionType.AiAgent | NodeConnectionType.AiChain | NodeConnectionType.AiDocument | NodeConnectionType.AiVectorStore | NodeConnectionType.AiRetriever; function determineArticle(nextWord: string): string { // check if the next word starts with a vowel sound const vowels = /^[aeiouAEIOU]/; return vowels.test(nextWord) ? 'an' : 'a'; } const getAhref = (connectionType: { connection: string; locale: string }) => `${connectionType.locale}`; export function getConnectionHintNoticeField( connectionTypes: AllowedConnectionTypes[], ): INodeProperties { const groupedConnections = new Map(); // group connection types by their 'connection' value // to not create multiple links connectionTypes.forEach((connectionType) => { const connectionString = connectionsString[connectionType].connection; const localeString = connectionsString[connectionType].locale; if (!groupedConnections.has(connectionString)) { groupedConnections.set(connectionString, [localeString]); return; } groupedConnections.get(connectionString)?.push(localeString); }); let displayName; if (groupedConnections.size === 1) { const [[connection, locales]] = Array.from(groupedConnections); displayName = `This node must be connected to ${determineArticle(locales[0])} ${locales[0] .toLowerCase() .replace( /^ai /, 'AI ', )}. Insert one`; } else { const ahrefs = Array.from(groupedConnections, ([connection, locales]) => { // If there are multiple locales, join them with ' or ' // use determineArticle to insert the correct article const locale = locales.length > 1 ? locales .map((localeString, index, { length }) => { return ( (index === 0 ? `${determineArticle(localeString)} ` : '') + (index < length - 1 ? `${localeString} or ` : localeString) ); }) .join('') : `${determineArticle(locales[0])} ${locales[0]}`; return getAhref({ connection, locale }); }); displayName = `This node needs to be connected to ${ahrefs.join(' or ')}.`; } return { displayName, name: 'notice', type: 'notice', default: '', typeOptions: { containerClass: 'ndv-connection-hint-notice', }, }; }