mirror of
				https://github.com/n8n-io/n8n-nodes-starter.git
				synced 2025-10-31 07:12:25 -05:00 
			
		
		
		
	feat: initialize base agent node
This commit is contained in:
		
					parent
					
						
							
								e33348ac69
							
						
					
				
			
			
				commit
				
					
						2fbccb3423
					
				
			
		
					 13 changed files with 8082 additions and 536 deletions
				
			
		
							
								
								
									
										66
									
								
								credentials/BaseApi.credentials.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								credentials/BaseApi.credentials.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | import { | ||||||
|  | 	IAuthenticateGeneric, | ||||||
|  | 	ICredentialTestRequest, | ||||||
|  | 	ICredentialType, | ||||||
|  | 	INodeProperties, | ||||||
|  | } from 'n8n-workflow'; | ||||||
|  | 
 | ||||||
|  | export class BaseApi implements ICredentialType { | ||||||
|  | 	name = 'baseApi'; | ||||||
|  | 	displayName = 'Base API'; | ||||||
|  | 	documentationUrl = 'https://docs.base.com/'; | ||||||
|  | 	properties: INodeProperties[] = [ | ||||||
|  | 		{ | ||||||
|  | 			displayName: 'Private Key', | ||||||
|  | 			name: 'privateKey', | ||||||
|  | 			type: 'string', | ||||||
|  | 			typeOptions: { | ||||||
|  | 				password: true, | ||||||
|  | 			}, | ||||||
|  | 			default: '', | ||||||
|  | 			required: true, | ||||||
|  | 			description: 'The private key of your Base wallet', | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			displayName: 'RPC URL', | ||||||
|  | 			name: 'rpcUrl', | ||||||
|  | 			type: 'string', | ||||||
|  | 			default: 'https://api.mainnet-beta.base.com', | ||||||
|  | 			required: true, | ||||||
|  | 			description: 'The URL of the Base RPC node', | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			displayName: 'OpenAI API Key', | ||||||
|  | 			name: 'openAiApiKey', | ||||||
|  | 			type: 'string', | ||||||
|  | 			typeOptions: { | ||||||
|  | 				password: true, | ||||||
|  | 			}, | ||||||
|  | 			default: '', | ||||||
|  | 			required: true, | ||||||
|  | 			description: 'API key for OpenAI services', | ||||||
|  | 		}, | ||||||
|  | 	]; | ||||||
|  | 
 | ||||||
|  | 	authenticate: IAuthenticateGeneric = { | ||||||
|  | 		type: 'generic', | ||||||
|  | 		properties: { | ||||||
|  | 			headers: { | ||||||
|  | 				'Content-Type': 'application/json', | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	test: ICredentialTestRequest = { | ||||||
|  | 		request: { | ||||||
|  | 			baseURL: '={{$credentials.rpcUrl}}', | ||||||
|  | 			url: '/', | ||||||
|  | 			method: 'POST', | ||||||
|  | 			body: { | ||||||
|  | 				jsonrpc: '2.0', | ||||||
|  | 				id: 1, | ||||||
|  | 				method: 'getHealth', | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	}; | ||||||
|  | }  | ||||||
|  | @ -1,56 +0,0 @@ | ||||||
| import { |  | ||||||
| 	IAuthenticateGeneric, |  | ||||||
| 	ICredentialTestRequest, |  | ||||||
| 	ICredentialType, |  | ||||||
| 	INodeProperties, |  | ||||||
| } from 'n8n-workflow'; |  | ||||||
| 
 |  | ||||||
| export class ExampleCredentialsApi implements ICredentialType { |  | ||||||
| 	name = 'exampleCredentialsApi'; |  | ||||||
| 	displayName = 'Example Credentials API'; |  | ||||||
| 	properties: INodeProperties[] = [ |  | ||||||
| 		// The credentials to get from user and save encrypted.
 |  | ||||||
| 		// Properties can be defined exactly in the same way
 |  | ||||||
| 		// as node properties.
 |  | ||||||
| 		{ |  | ||||||
| 			displayName: 'User Name', |  | ||||||
| 			name: 'username', |  | ||||||
| 			type: 'string', |  | ||||||
| 			default: '', |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			displayName: 'Password', |  | ||||||
| 			name: 'password', |  | ||||||
| 			type: 'string', |  | ||||||
| 			typeOptions: { |  | ||||||
| 				password: true, |  | ||||||
| 			}, |  | ||||||
| 			default: '', |  | ||||||
| 		}, |  | ||||||
| 	]; |  | ||||||
| 
 |  | ||||||
| 	// This credential is currently not used by any node directly
 |  | ||||||
| 	// but the HTTP Request node can use it to make requests.
 |  | ||||||
| 	// The credential is also testable due to the `test` property below
 |  | ||||||
| 	authenticate: IAuthenticateGeneric = { |  | ||||||
| 		type: 'generic', |  | ||||||
| 		properties: { |  | ||||||
| 			auth: { |  | ||||||
| 				username: '={{ $credentials.username }}', |  | ||||||
| 				password: '={{ $credentials.password }}', |  | ||||||
| 			}, |  | ||||||
| 			qs: { |  | ||||||
| 				// Send this as part of the query string
 |  | ||||||
| 				n8n: 'rocks', |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	// The block below tells how this credential can be tested
 |  | ||||||
| 	test: ICredentialTestRequest = { |  | ||||||
| 		request: { |  | ||||||
| 			baseURL: 'https://example.com/', |  | ||||||
| 			url: '', |  | ||||||
| 		}, |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| import { |  | ||||||
| 	IAuthenticateGeneric, |  | ||||||
| 	ICredentialTestRequest, |  | ||||||
| 	ICredentialType, |  | ||||||
| 	INodeProperties, |  | ||||||
| } from 'n8n-workflow'; |  | ||||||
| 
 |  | ||||||
| export class HttpBinApi implements ICredentialType { |  | ||||||
| 	name = 'httpbinApi'; |  | ||||||
| 	displayName = 'HttpBin API'; |  | ||||||
| 	documentationUrl = '<your-docs-url>'; |  | ||||||
| 	properties: INodeProperties[] = [ |  | ||||||
| 		{ |  | ||||||
| 			displayName: 'Token', |  | ||||||
| 			name: 'token', |  | ||||||
| 			type: 'string', |  | ||||||
| 			default: '', |  | ||||||
| 			typeOptions: { |  | ||||||
| 				password: true, |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			displayName: 'Domain', |  | ||||||
| 			name: 'domain', |  | ||||||
| 			type: 'string', |  | ||||||
| 			default: 'https://httpbin.org', |  | ||||||
| 		}, |  | ||||||
| 	]; |  | ||||||
| 
 |  | ||||||
| 	// This allows the credential to be used by other parts of n8n
 |  | ||||||
| 	// stating how this credential is injected as part of the request
 |  | ||||||
| 	// An example is the Http Request node that can make generic calls
 |  | ||||||
| 	// reusing this credential
 |  | ||||||
| 	authenticate: IAuthenticateGeneric = { |  | ||||||
| 		type: 'generic', |  | ||||||
| 		properties: { |  | ||||||
| 			headers: { |  | ||||||
| 				Authorization: '={{"Bearer " + $credentials.token}}', |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	// The block below tells how this credential can be tested
 |  | ||||||
| 	test: ICredentialTestRequest = { |  | ||||||
| 		request: { |  | ||||||
| 			baseURL: '={{$credentials?.domain}}', |  | ||||||
| 			url: '/bearer', |  | ||||||
| 		}, |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
							
								
								
									
										272
									
								
								nodes/BaseAgent/BaseAgent.node.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								nodes/BaseAgent/BaseAgent.node.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,272 @@ | ||||||
|  | import { | ||||||
|  | 	IExecuteFunctions, | ||||||
|  | 	INodeExecutionData, | ||||||
|  | 	INodeType, | ||||||
|  | 	INodeTypeDescription, | ||||||
|  | 	NodeOperationError, | ||||||
|  | } from 'n8n-workflow'; | ||||||
|  | 
 | ||||||
|  | class BaseAgent implements INodeType { | ||||||
|  | 	description: INodeTypeDescription = { | ||||||
|  | 		displayName: 'Base Agent', | ||||||
|  | 		name: 'baseAgent', | ||||||
|  | 		icon: 'file:base.svg', | ||||||
|  | 		group: ['blockchain'], | ||||||
|  | 		version: 1, | ||||||
|  | 		subtitle: '={{$parameter["operation"]}}', | ||||||
|  | 		description: 'Interact with Base onchain AI agents', | ||||||
|  | 		defaults: { | ||||||
|  | 			name: 'Base Agent', | ||||||
|  | 		}, | ||||||
|  | 		inputs: ['main'], | ||||||
|  | 		outputs: ['main'], | ||||||
|  | 		credentials: [ | ||||||
|  | 			{ | ||||||
|  | 				name: 'baseApi', | ||||||
|  | 				required: true, | ||||||
|  | 			}, | ||||||
|  | 		], | ||||||
|  | 		properties: [ | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Operation', | ||||||
|  | 				name: 'operation', | ||||||
|  | 				type: 'options', | ||||||
|  | 				noDataExpression: true, | ||||||
|  | 				// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
 | ||||||
|  | 				options: [ | ||||||
|  | 					{ | ||||||
|  | 						name: 'Create Token', | ||||||
|  | 						value: 'createToken', | ||||||
|  | 						description: 'Create a new token', | ||||||
|  | 						action: 'Create a new token', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Transfer Token', | ||||||
|  | 						value: 'transferToken', | ||||||
|  | 						description: 'Transfer tokens', | ||||||
|  | 						action: 'Transfer tokens', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Get Token Balances', | ||||||
|  | 						value: 'getTokenBalances', | ||||||
|  | 						description: 'Get all token balances for a wallet', | ||||||
|  | 						action: 'Get token balances', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Get Single Token Balance', | ||||||
|  | 						value: 'getSingleBalance', | ||||||
|  | 						description: 'Get balance for a specific token', | ||||||
|  | 						action: 'Get single token balance', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Get Other Wallet Balance', | ||||||
|  | 						value: 'getOtherBalance', | ||||||
|  | 						description: 'Get token balance for another wallet', | ||||||
|  | 						action: 'Get other wallet balance', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Close Empty Token Accounts', | ||||||
|  | 						value: 'closeEmptyTokenAccounts', | ||||||
|  | 						action: 'Close empty token accounts', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Request Faucet Funds', | ||||||
|  | 						value: 'requestFaucet', | ||||||
|  | 						description: 'Request SOL from faucet (devnet/testnet)', | ||||||
|  | 						action: 'Request faucet funds', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Get Network TPS', | ||||||
|  | 						value: 'getTPS', | ||||||
|  | 						description: 'Get current network TPS', | ||||||
|  | 						action: 'Get network TPS', | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						name: 'Get Wallet Address', | ||||||
|  | 						value: 'getWalletAddress', | ||||||
|  | 						description: 'Get current wallet address', | ||||||
|  | 						action: 'Get wallet address', | ||||||
|  | 					}, | ||||||
|  | 				], | ||||||
|  | 				default: 'createToken', | ||||||
|  | 			}, | ||||||
|  | 			// Token Creation Parameters
 | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Token Name', | ||||||
|  | 				name: 'tokenName', | ||||||
|  | 				type: 'string', | ||||||
|  | 				typeOptions: { password: true }, | ||||||
|  | 				required: true, | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['createToken'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: '', | ||||||
|  | 				description: 'Name of the token to create', | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Token Symbol', | ||||||
|  | 				name: 'tokenSymbol', | ||||||
|  | 				type: 'string', | ||||||
|  | 				typeOptions: { password: true }, | ||||||
|  | 				required: true, | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['createToken'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: '', | ||||||
|  | 				description: 'Symbol of the token to create', | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Decimals', | ||||||
|  | 				name: 'decimals', | ||||||
|  | 				type: 'number', | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['createToken'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: 9, | ||||||
|  | 				description: 'Number of decimal places for the token', | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Initial Supply', | ||||||
|  | 				name: 'initialSupply', | ||||||
|  | 				type: 'number', | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['createToken'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: 0, | ||||||
|  | 				description: 'Initial supply of tokens to mint', | ||||||
|  | 			}, | ||||||
|  | 			// Transfer Parameters
 | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Recipient Address', | ||||||
|  | 				name: 'recipientAddress', | ||||||
|  | 				type: 'string', | ||||||
|  | 				required: true, | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['transferToken'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: '', | ||||||
|  | 				description: 'Recipient wallet address', | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Amount', | ||||||
|  | 				name: 'amount', | ||||||
|  | 				type: 'number', | ||||||
|  | 				required: true, | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['transferToken'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: 0, | ||||||
|  | 				description: 'Amount to transfer', | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Token Address', | ||||||
|  | 				name: 'tokenAddress', | ||||||
|  | 				type: 'string', | ||||||
|  | 				typeOptions: { password: true }, | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['transferToken', 'getSingleBalance'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: '', | ||||||
|  | 				description: 'SPL token address (leave empty for SOL)', | ||||||
|  | 			}, | ||||||
|  | 			// Balance Parameters
 | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Wallet Address', | ||||||
|  | 				name: 'walletAddress', | ||||||
|  | 				type: 'string', | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['getTokenBalances', 'getOtherBalance'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: '', | ||||||
|  | 				description: 'Wallet address to check balances for (leave empty for own wallet)', | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				displayName: 'Token Address for Other Wallet', | ||||||
|  | 				name: 'otherTokenAddress', | ||||||
|  | 				type: 'string', | ||||||
|  | 				typeOptions: { password: true }, | ||||||
|  | 				displayOptions: { | ||||||
|  | 					show: { | ||||||
|  | 						operation: ['getOtherBalance'], | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				default: '', | ||||||
|  | 				description: 'Token address to check balance for (leave empty for SOL)', | ||||||
|  | 			}, | ||||||
|  | 		], | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { | ||||||
|  | 		const items = this.getInputData(); | ||||||
|  | 		const returnData: INodeExecutionData[] = []; | ||||||
|  | 		const operation = this.getNodeParameter('operation', 0) as string; | ||||||
|  | 		 | ||||||
|  | 		// Get credentials
 | ||||||
|  | 		const credentials = await this.getCredentials('baseApi'); | ||||||
|  | 		const rpcUrl = credentials.rpcUrl; | ||||||
|  | 		rpcUrl | ||||||
|  | 		// Initialize Wallet
 | ||||||
|  | 		 | ||||||
|  | 		// Initialize Base Agent Kit
 | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 		for (let i = 0; i < items.length; i++) { | ||||||
|  | 			try { | ||||||
|  | 				let result; | ||||||
|  | 				 | ||||||
|  | 				switch (operation) { | ||||||
|  | 
 | ||||||
|  | 					//TODO: define base on chain actions
 | ||||||
|  | 					case 'transferToken': | ||||||
|  | 						// const recipientAddress = new PublicKey(this.getNodeParameter('recipientAddress', i) as string);
 | ||||||
|  | 						// const amount = this.getNodeParameter('amount', i) as number;
 | ||||||
|  | 						// const tokenAddress = this.getNodeParameter('tokenAddress', i) as string;
 | ||||||
|  | 						// const mintAddress = tokenAddress ? new PublicKey(tokenAddress) : undefined;
 | ||||||
|  | 						// result = await agent.methods.transfer(agent, recipientAddress, amount, mintAddress);
 | ||||||
|  | 						break; | ||||||
|  | 
 | ||||||
|  | 					 | ||||||
|  | 					default: | ||||||
|  | 						throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				returnData.push({ | ||||||
|  | 					json: {result}, | ||||||
|  | 				}); | ||||||
|  | 			} catch (error) { | ||||||
|  | 				if (this.continueOnFail()) { | ||||||
|  | 					returnData.push({ | ||||||
|  | 						json: { | ||||||
|  | 							error: error.message, | ||||||
|  | 						}, | ||||||
|  | 					}); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				throw error; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		return [returnData]; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Export the class
 | ||||||
|  | export { BaseAgent };  | ||||||
							
								
								
									
										14
									
								
								nodes/BaseAgent/base.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								nodes/BaseAgent/base.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | <svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||||
|  | <g filter="url(#filter0_b_139_1266)"> | ||||||
|  | <rect width="46" height="46" rx="23" fill="black" fill-opacity="0.9"/> | ||||||
|  | <path d="M22.9803 34.3703C29.2728 34.3703 34.3739 29.2796 34.3739 23.0001C34.3739 16.7205 29.2728 11.6299 22.9803 11.6299C17.0104 11.6299 12.1129 16.212 11.6265 22.0443H26.6861V23.9558H11.6265C12.1129 29.7882 17.0104 34.3703 22.9803 34.3703Z" fill="#E3E7E9"/> | ||||||
|  | </g> | ||||||
|  | <defs> | ||||||
|  | <filter id="filter0_b_139_1266" x="-14" y="-14" width="74" height="74" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||||
|  | <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||||
|  | <feGaussianBlur in="BackgroundImageFix" stdDeviation="7"/> | ||||||
|  | <feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_139_1266"/> | ||||||
|  | <feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_139_1266" result="shape"/> | ||||||
|  | </filter> | ||||||
|  | </defs> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 939 B | 
|  | @ -1,76 +0,0 @@ | ||||||
| import type { |  | ||||||
| 	IExecuteFunctions, |  | ||||||
| 	INodeExecutionData, |  | ||||||
| 	INodeType, |  | ||||||
| 	INodeTypeDescription, |  | ||||||
| } from 'n8n-workflow'; |  | ||||||
| import { NodeConnectionType, NodeOperationError } from 'n8n-workflow'; |  | ||||||
| 
 |  | ||||||
| export class ExampleNode implements INodeType { |  | ||||||
| 	description: INodeTypeDescription = { |  | ||||||
| 		displayName: 'Example Node', |  | ||||||
| 		name: 'exampleNode', |  | ||||||
| 		group: ['transform'], |  | ||||||
| 		version: 1, |  | ||||||
| 		description: 'Basic Example Node', |  | ||||||
| 		defaults: { |  | ||||||
| 			name: 'Example Node', |  | ||||||
| 		}, |  | ||||||
| 		inputs: [NodeConnectionType.Main], |  | ||||||
| 		outputs: [NodeConnectionType.Main], |  | ||||||
| 		properties: [ |  | ||||||
| 			// Node properties which the user gets displayed and
 |  | ||||||
| 			// can change on the node.
 |  | ||||||
| 			{ |  | ||||||
| 				displayName: 'My String', |  | ||||||
| 				name: 'myString', |  | ||||||
| 				type: 'string', |  | ||||||
| 				default: '', |  | ||||||
| 				placeholder: 'Placeholder value', |  | ||||||
| 				description: 'The description text', |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	// The function below is responsible for actually doing whatever this node
 |  | ||||||
| 	// is supposed to do. In this case, we're just appending the `myString` property
 |  | ||||||
| 	// with whatever the user has entered.
 |  | ||||||
| 	// You can make async calls and use `await`.
 |  | ||||||
| 	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { |  | ||||||
| 		const items = this.getInputData(); |  | ||||||
| 
 |  | ||||||
| 		let item: INodeExecutionData; |  | ||||||
| 		let myString: string; |  | ||||||
| 
 |  | ||||||
| 		// Iterates over all input items and add the key "myString" with the
 |  | ||||||
| 		// value the parameter "myString" resolves to.
 |  | ||||||
| 		// (This could be a different value for each item in case it contains an expression)
 |  | ||||||
| 		for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { |  | ||||||
| 			try { |  | ||||||
| 				myString = this.getNodeParameter('myString', itemIndex, '') as string; |  | ||||||
| 				item = items[itemIndex]; |  | ||||||
| 
 |  | ||||||
| 				item.json.myString = myString; |  | ||||||
| 			} catch (error) { |  | ||||||
| 				// This node should never fail but we want to showcase how
 |  | ||||||
| 				// to handle errors.
 |  | ||||||
| 				if (this.continueOnFail()) { |  | ||||||
| 					items.push({ json: this.getInputData(itemIndex)[0].json, error, pairedItem: itemIndex }); |  | ||||||
| 				} else { |  | ||||||
| 					// Adding `itemIndex` allows other workflows to handle this error
 |  | ||||||
| 					if (error.context) { |  | ||||||
| 						// If the error thrown already contains the context property,
 |  | ||||||
| 						// only append the itemIndex
 |  | ||||||
| 						error.context.itemIndex = itemIndex; |  | ||||||
| 						throw error; |  | ||||||
| 					} |  | ||||||
| 					throw new NodeOperationError(this.getNode(), error, { |  | ||||||
| 						itemIndex, |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return [items]; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| { |  | ||||||
| 	"node": "n8n-nodes-base.httpbin", |  | ||||||
| 	"nodeVersion": "1.0", |  | ||||||
| 	"codexVersion": "1.0", |  | ||||||
| 	"categories": ["Development", "Developer Tools"], |  | ||||||
| 	"resources": { |  | ||||||
| 		"credentialDocumentation": [ |  | ||||||
| 			{ |  | ||||||
| 				"url": "http://httpbin.org/#/Auth/get_bearer" |  | ||||||
| 			} |  | ||||||
| 		], |  | ||||||
| 		"primaryDocumentation": [ |  | ||||||
| 			{ |  | ||||||
| 				"url": "http://httpbin.org/" |  | ||||||
| 			} |  | ||||||
| 		] |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,62 +0,0 @@ | ||||||
| import { INodeType, INodeTypeDescription } from 'n8n-workflow'; |  | ||||||
| import { httpVerbFields, httpVerbOperations } from './HttpVerbDescription'; |  | ||||||
| 
 |  | ||||||
| export class HttpBin implements INodeType { |  | ||||||
| 	description: INodeTypeDescription = { |  | ||||||
| 		displayName: 'HttpBin', |  | ||||||
| 		name: 'httpBin', |  | ||||||
| 		icon: 'file:httpbin.svg', |  | ||||||
| 		group: ['transform'], |  | ||||||
| 		version: 1, |  | ||||||
| 		subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', |  | ||||||
| 		description: 'Interact with HttpBin API', |  | ||||||
| 		defaults: { |  | ||||||
| 			name: 'HttpBin', |  | ||||||
| 		}, |  | ||||||
| 		inputs: ['main'], |  | ||||||
| 		outputs: ['main'], |  | ||||||
| 		credentials: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'httpbinApi', |  | ||||||
| 				required: false, |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		requestDefaults: { |  | ||||||
| 			baseURL: 'https://httpbin.org', |  | ||||||
| 			url: '', |  | ||||||
| 			headers: { |  | ||||||
| 				Accept: 'application/json', |  | ||||||
| 				'Content-Type': 'application/json', |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		/** |  | ||||||
| 		 * In the properties array we have two mandatory options objects required |  | ||||||
| 		 * |  | ||||||
| 		 * [Resource & Operation] |  | ||||||
| 		 * |  | ||||||
| 		 * https://docs.n8n.io/integrations/creating-nodes/code/create-first-node/#resources-and-operations
 |  | ||||||
| 		 * |  | ||||||
| 		 * In our example, the operations are separated into their own file (HTTPVerbDescription.ts) |  | ||||||
| 		 * to keep this class easy to read. |  | ||||||
| 		 * |  | ||||||
| 		 */ |  | ||||||
| 		properties: [ |  | ||||||
| 			{ |  | ||||||
| 				displayName: 'Resource', |  | ||||||
| 				name: 'resource', |  | ||||||
| 				type: 'options', |  | ||||||
| 				noDataExpression: true, |  | ||||||
| 				options: [ |  | ||||||
| 					{ |  | ||||||
| 						name: 'HTTP Verb', |  | ||||||
| 						value: 'httpVerb', |  | ||||||
| 					}, |  | ||||||
| 				], |  | ||||||
| 				default: 'httpVerb', |  | ||||||
| 			}, |  | ||||||
| 
 |  | ||||||
| 			...httpVerbOperations, |  | ||||||
| 			...httpVerbFields, |  | ||||||
| 		], |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
|  | @ -1,248 +0,0 @@ | ||||||
| import { INodeProperties } from 'n8n-workflow'; |  | ||||||
| 
 |  | ||||||
| // When the resource `httpVerb` is selected, this `operation` parameter will be shown.
 |  | ||||||
| export const httpVerbOperations: INodeProperties[] = [ |  | ||||||
| 	{ |  | ||||||
| 		displayName: 'Operation', |  | ||||||
| 		name: 'operation', |  | ||||||
| 		type: 'options', |  | ||||||
| 		noDataExpression: true, |  | ||||||
| 
 |  | ||||||
| 		displayOptions: { |  | ||||||
| 			show: { |  | ||||||
| 				resource: ['httpVerb'], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		options: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'GET', |  | ||||||
| 				value: 'get', |  | ||||||
| 				description: 'Perform a GET request', |  | ||||||
| 				routing: { |  | ||||||
| 					request: { |  | ||||||
| 						method: 'GET', |  | ||||||
| 						url: '/get', |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name: 'DELETE', |  | ||||||
| 				value: 'delete', |  | ||||||
| 				description: 'Perform a DELETE request', |  | ||||||
| 				routing: { |  | ||||||
| 					request: { |  | ||||||
| 						method: 'DELETE', |  | ||||||
| 						url: '/delete', |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		default: 'get', |  | ||||||
| 	}, |  | ||||||
| ]; |  | ||||||
| 
 |  | ||||||
| // Here we define what to show when the `get` operation is selected.
 |  | ||||||
| // We do that by adding `operation: ["get"]` to `displayOptions.show`
 |  | ||||||
| const getOperation: INodeProperties[] = [ |  | ||||||
| 	{ |  | ||||||
| 		displayName: 'Type of Data', |  | ||||||
| 		name: 'typeofData', |  | ||||||
| 		default: 'queryParameter', |  | ||||||
| 		description: 'Select type of data to send [Query Parameters]', |  | ||||||
| 		displayOptions: { |  | ||||||
| 			show: { |  | ||||||
| 				resource: ['httpVerb'], |  | ||||||
| 				operation: ['get'], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		type: 'options', |  | ||||||
| 		options: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'Query', |  | ||||||
| 				value: 'queryParameter', |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		required: true, |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		displayName: 'Query Parameters', |  | ||||||
| 		name: 'arguments', |  | ||||||
| 		default: {}, |  | ||||||
| 		description: "The request's query parameters", |  | ||||||
| 		displayOptions: { |  | ||||||
| 			show: { |  | ||||||
| 				resource: ['httpVerb'], |  | ||||||
| 				operation: ['get'], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		options: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'keyvalue', |  | ||||||
| 				displayName: 'Key:Value', |  | ||||||
| 				values: [ |  | ||||||
| 					{ |  | ||||||
| 						displayName: 'Key', |  | ||||||
| 						name: 'key', |  | ||||||
| 						type: 'string', |  | ||||||
| 						default: '', |  | ||||||
| 						required: true, |  | ||||||
| 						description: 'Key of query parameter', |  | ||||||
| 					}, |  | ||||||
| 					{ |  | ||||||
| 						displayName: 'Value', |  | ||||||
| 						name: 'value', |  | ||||||
| 						type: 'string', |  | ||||||
| 						default: '', |  | ||||||
| 						routing: { |  | ||||||
| 							send: { |  | ||||||
| 								property: '={{$parent.key}}', |  | ||||||
| 								type: 'query', |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 						required: true, |  | ||||||
| 						description: 'Value of query parameter', |  | ||||||
| 					}, |  | ||||||
| 				], |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		type: 'fixedCollection', |  | ||||||
| 		typeOptions: { |  | ||||||
| 			multipleValues: true, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| ]; |  | ||||||
| 
 |  | ||||||
| // Here we define what to show when the DELETE Operation is selected.
 |  | ||||||
| // We do that by adding `operation: ["delete"]` to `displayOptions.show`
 |  | ||||||
| const deleteOperation: INodeProperties[] = [ |  | ||||||
| 	{ |  | ||||||
| 		displayName: 'Type of Data', |  | ||||||
| 		name: 'typeofData', |  | ||||||
| 		default: 'queryParameter', |  | ||||||
| 		description: 'Select type of data to send [Query Parameter Arguments, JSON-Body]', |  | ||||||
| 		displayOptions: { |  | ||||||
| 			show: { |  | ||||||
| 				resource: ['httpVerb'], |  | ||||||
| 				operation: ['delete'], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		options: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'Query', |  | ||||||
| 				value: 'queryParameter', |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				name: 'JSON', |  | ||||||
| 				value: 'jsonData', |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		required: true, |  | ||||||
| 		type: 'options', |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		displayName: 'Query Parameters', |  | ||||||
| 		name: 'arguments', |  | ||||||
| 		default: {}, |  | ||||||
| 		description: "The request's query parameters", |  | ||||||
| 		displayOptions: { |  | ||||||
| 			show: { |  | ||||||
| 				resource: ['httpVerb'], |  | ||||||
| 				operation: ['delete'], |  | ||||||
| 				typeofData: ['queryParameter'], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		options: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'keyvalue', |  | ||||||
| 				displayName: 'Key:Value', |  | ||||||
| 				values: [ |  | ||||||
| 					{ |  | ||||||
| 						displayName: 'Key', |  | ||||||
| 						name: 'key', |  | ||||||
| 						type: 'string', |  | ||||||
| 						default: '', |  | ||||||
| 						required: true, |  | ||||||
| 						description: 'Key of query parameter', |  | ||||||
| 					}, |  | ||||||
| 					{ |  | ||||||
| 						displayName: 'Value', |  | ||||||
| 						name: 'value', |  | ||||||
| 						type: 'string', |  | ||||||
| 						default: '', |  | ||||||
| 						routing: { |  | ||||||
| 							send: { |  | ||||||
| 								property: '={{$parent.key}}', |  | ||||||
| 								type: 'query', |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 						required: true, |  | ||||||
| 						description: 'Value of query parameter', |  | ||||||
| 					}, |  | ||||||
| 				], |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		type: 'fixedCollection', |  | ||||||
| 		typeOptions: { |  | ||||||
| 			multipleValues: true, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	{ |  | ||||||
| 		displayName: 'JSON Object', |  | ||||||
| 		name: 'arguments', |  | ||||||
| 		default: {}, |  | ||||||
| 		description: "The request's JSON properties", |  | ||||||
| 		displayOptions: { |  | ||||||
| 			show: { |  | ||||||
| 				resource: ['httpVerb'], |  | ||||||
| 				operation: ['delete'], |  | ||||||
| 				typeofData: ['jsonData'], |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		options: [ |  | ||||||
| 			{ |  | ||||||
| 				name: 'keyvalue', |  | ||||||
| 				displayName: 'Key:Value', |  | ||||||
| 				values: [ |  | ||||||
| 					{ |  | ||||||
| 						displayName: 'Key', |  | ||||||
| 						name: 'key', |  | ||||||
| 						type: 'string', |  | ||||||
| 						default: '', |  | ||||||
| 						required: true, |  | ||||||
| 						description: 'Key of JSON property', |  | ||||||
| 					}, |  | ||||||
| 					{ |  | ||||||
| 						displayName: 'Value', |  | ||||||
| 						name: 'value', |  | ||||||
| 						type: 'string', |  | ||||||
| 						default: '', |  | ||||||
| 						routing: { |  | ||||||
| 							send: { |  | ||||||
| 								property: '={{$parent.key}}', |  | ||||||
| 								type: 'body', |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 						required: true, |  | ||||||
| 						description: 'Value of JSON property', |  | ||||||
| 					}, |  | ||||||
| 				], |  | ||||||
| 			}, |  | ||||||
| 		], |  | ||||||
| 		type: 'fixedCollection', |  | ||||||
| 		typeOptions: { |  | ||||||
| 			multipleValues: true, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| ]; |  | ||||||
| 
 |  | ||||||
| export const httpVerbFields: INodeProperties[] = [ |  | ||||||
| 	/* -------------------------------------------------------------------------- */ |  | ||||||
| 	/*                                httpVerb:get                                */ |  | ||||||
| 	/* -------------------------------------------------------------------------- */ |  | ||||||
| 	...getOperation, |  | ||||||
| 
 |  | ||||||
| 	/* -------------------------------------------------------------------------- */ |  | ||||||
| 	/*                              httpVerb:delete                               */ |  | ||||||
| 	/* -------------------------------------------------------------------------- */ |  | ||||||
| 	...deleteOperation, |  | ||||||
| ]; |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> |  | ||||||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> |  | ||||||
| <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">  <image id="image0" width="32" height="32" x="0" y="0" |  | ||||||
|     href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAALGPC/xhBQAAACBjSFJN |  | ||||||
| AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElN |  | ||||||
| RQfmBg4UAC/TqOZZAAACA0lEQVRIx5XVv09TURwF8M+jFHDSyRkGFhPAEfyRdDHi5uriXyDoYgKT |  | ||||||
| MJDWzUT/Ahf/AiOEpajEgCESmpiYmDCxGowDTYE+h76+vte+15Zzk753b7733HNO772PbEw7ECba |  | ||||||
| genswtEcgl0/PHARV72066YrIDSZ6k8KBym4741r0XsB284TdUX8chn1zrzwJUmw4KFXPqjFE0Y0 |  | ||||||
| u5YKEhpmfLZuy7f2wLKGI8WhDRYdaVhurdTCidmU5P44N+skaaGQH1IfFFrOYMotT932zNgQExve |  | ||||||
| OfTeT8dtBceO3TFlOyopY7UPxV+/fWyn3Y0xrFhJjZWFXhs12pKdRO9ObGSuyB8Xbd9JjMjDc6HQ |  | ||||||
| IcrKqAiVe8vyCEJPrGBWxZYqqtZt9RbmHabAvAAVdVUlJTvWshbMt0AYn40OmlchSKOePTyYIMQn |  | ||||||
| rb8yI8TsDCrRs4od7Jv3KOoPGWKboBqp2LN3FQvdO7EPshSsRSTXrSop2cSiiUGkG/bj2JqaQiHW |  | ||||||
| 4nv50mFcu28j30KQarAnEPhuzvwwGYQ975vx7+JwGXTjTIAzoYlhCArR5d0KkfauqJAVY6+FG5hD |  | ||||||
| OS6veqyCuSiTAQT/jKmlQtyxIBCoZV28HQvN6LuQvJFC4xjvibfYOZUdUXd9taTWJbOubiIVXmjG |  | ||||||
| W/fs9qpZcpr6pOe1U0udSf8BR7ef4yxyOskAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjItMDYtMTRU |  | ||||||
| MTc6MDA6NDcrMDM6MDBfo1sRAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIyLTA2LTE0VDE3OjAwOjQ3 |  | ||||||
| KzAzOjAwLv7jrQAAAABJRU5ErkJggg==" /> |  | ||||||
| </svg> |  | ||||||
| Before Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										7723
									
								
								package-lock.json
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7723
									
								
								package-lock.json
									
										
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -36,12 +36,10 @@ | ||||||
|   "n8n": { |   "n8n": { | ||||||
|     "n8nNodesApiVersion": 1, |     "n8nNodesApiVersion": 1, | ||||||
|     "credentials": [ |     "credentials": [ | ||||||
|       "dist/credentials/ExampleCredentialsApi.credentials.js", |       "dist/credentials/BaseApi.credentials.js" | ||||||
|       "dist/credentials/HttpBinApi.credentials.js" |  | ||||||
|     ], |     ], | ||||||
|     "nodes": [ |     "nodes": [ | ||||||
|       "dist/nodes/ExampleNode/ExampleNode.node.js", |       "dist/nodes/BaseAgent/BaseAgent.node.js" | ||||||
|       "dist/nodes/HttpBin/HttpBin.node.js" |  | ||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							|  | @ -7,6 +7,10 @@ settings: | ||||||
| importers: | importers: | ||||||
| 
 | 
 | ||||||
|   .: |   .: | ||||||
|  |     dependencies: | ||||||
|  |       n8n-workflow: | ||||||
|  |         specifier: '*' | ||||||
|  |         version: 1.48.0 | ||||||
|     devDependencies: |     devDependencies: | ||||||
|       '@typescript-eslint/parser': |       '@typescript-eslint/parser': | ||||||
|         specifier: ^7.15.0 |         specifier: ^7.15.0 | ||||||
|  | @ -20,9 +24,6 @@ importers: | ||||||
|       gulp: |       gulp: | ||||||
|         specifier: ^4.0.2 |         specifier: ^4.0.2 | ||||||
|         version: 4.0.2 |         version: 4.0.2 | ||||||
|       n8n-workflow: |  | ||||||
|         specifier: '*' |  | ||||||
|         version: 1.48.0 |  | ||||||
|       prettier: |       prettier: | ||||||
|         specifier: ^3.3.2 |         specifier: ^3.3.2 | ||||||
|         version: 3.3.2 |         version: 3.3.2 | ||||||
|  | @ -758,7 +759,7 @@ packages: | ||||||
|     resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} |     resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} | ||||||
|     engines: {node: '>= 4.0'} |     engines: {node: '>= 4.0'} | ||||||
|     os: [darwin] |     os: [darwin] | ||||||
|     deprecated: The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2 |     deprecated: Upgrade to fsevents v2 to mitigate potential security issues | ||||||
| 
 | 
 | ||||||
|   function-bind@1.1.2: |   function-bind@1.1.2: | ||||||
|     resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} |     resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue