Handle errors from example node and clarified options about credentials and properties
This commit is contained in:
		
					parent
					
						
							
								e2b4595066
							
						
					
				
			
			
				commit
				
					
						abe033d7a1
					
				
			
		
					 3 changed files with 38 additions and 30 deletions
				
			
		|  | @ -1,4 +1,5 @@ | ||||||
| import { | import { | ||||||
|  | 	IAuthenticateGeneric, | ||||||
| 	ICredentialDataDecryptedObject, | 	ICredentialDataDecryptedObject, | ||||||
| 	ICredentialTestRequest, | 	ICredentialTestRequest, | ||||||
| 	ICredentialType, | 	ICredentialType, | ||||||
|  | @ -17,12 +18,6 @@ export class HttpBinApi implements ICredentialType { | ||||||
| 			type: 'string', | 			type: 'string', | ||||||
| 			default: '', | 			default: '', | ||||||
| 		}, | 		}, | ||||||
| 		// {
 |  | ||||||
| 		// 	displayName: "API Key",
 |  | ||||||
| 		// 	name: "apiKey",
 |  | ||||||
| 		// 	type: "string",
 |  | ||||||
| 		// 	default: "",
 |  | ||||||
| 		// },
 |  | ||||||
| 		{ | 		{ | ||||||
| 			displayName: 'Domain', | 			displayName: 'Domain', | ||||||
| 			name: 'domain', | 			name: 'domain', | ||||||
|  | @ -31,26 +26,21 @@ export class HttpBinApi implements ICredentialType { | ||||||
| 		}, | 		}, | ||||||
| 	]; | 	]; | ||||||
| 
 | 
 | ||||||
| 	// authenticate = {
 | 	// This allows the credential to be used by other parts of n8n
 | ||||||
| 	// 	type: "headerAuth",
 | 	// stating how this credential is injected as part of the request
 | ||||||
| 	// 	properties: {
 | 	// An example is the Http Request node that can make generic calls
 | ||||||
| 	// 		name: "api-key",
 | 	// reusing this credential
 | ||||||
| 	// 		value: "={{$credentials.apiKey}}",
 | 	authenticate = { | ||||||
| 	// 	},
 | 		type: 'generic', | ||||||
| 	// } as IAuthenticateHeaderAuth;
 | 		properties: { | ||||||
| 
 | 			header: { | ||||||
| 	authenticate = async ( | 				name: 'api-key', | ||||||
| 		credentials: ICredentialDataDecryptedObject, | 				value: '={{$credentials.apiKey}}', | ||||||
| 		requestOptions: IHttpRequestOptions, | 			}, | ||||||
| 	): Promise<IHttpRequestOptions> => { | 		}, | ||||||
| 		const headers = requestOptions.headers || {}; | 	} as IAuthenticateGeneric; | ||||||
| 		const authentication = { Authorization: `Bearer ${credentials.token}` }; |  | ||||||
| 		Object.assign(requestOptions, { |  | ||||||
| 			headers: { ...authentication, ...headers }, |  | ||||||
| 		}); |  | ||||||
| 		return requestOptions; |  | ||||||
| 	}; |  | ||||||
| 
 | 
 | ||||||
|  | 	// The block below tells how this credential can be tested
 | ||||||
| 	test: ICredentialTestRequest = { | 	test: ICredentialTestRequest = { | ||||||
| 		request: { | 		request: { | ||||||
| 			baseURL: '={{$credentials?.domain}}', | 			baseURL: '={{$credentials?.domain}}', | ||||||
|  |  | ||||||
|  | @ -28,6 +28,10 @@ export class ExampleNode implements INodeType { | ||||||
| 		], | 		], | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	// 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[][]> { | 	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { | ||||||
| 		const items = this.getInputData(); | 		const items = this.getInputData(); | ||||||
| 
 | 
 | ||||||
|  | @ -38,10 +42,24 @@ export class ExampleNode implements INodeType { | ||||||
| 		// value the parameter "myString" resolves to.
 | 		// value the parameter "myString" resolves to.
 | ||||||
| 		// (This could be a different value for each item in case it contains an expression)
 | 		// (This could be a different value for each item in case it contains an expression)
 | ||||||
| 		for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { | 		for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { | ||||||
|  | 			try { | ||||||
| 				myString = this.getNodeParameter('myString', itemIndex, '') as string; | 				myString = this.getNodeParameter('myString', itemIndex, '') as string; | ||||||
| 				item = items[itemIndex]; | 				item = items[itemIndex]; | ||||||
| 
 | 
 | ||||||
| 				item.json['myString'] = myString; | 				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}); | ||||||
|  | 				} else { | ||||||
|  | 					// Adding `itemIndex` allows other workflows to handle this error
 | ||||||
|  | 					if (error.context) error.context.itemIndex = itemIndex; | ||||||
|  | 					throw error; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return this.prepareOutputData(items); | 		return this.prepareOutputData(items); | ||||||
|  |  | ||||||
|  | @ -42,8 +42,8 @@ | ||||||
|     "@typescript-eslint/parser": "^5.29.0", |     "@typescript-eslint/parser": "^5.29.0", | ||||||
|     "eslint-plugin-n8n-nodes-base": "~1.1.1", |     "eslint-plugin-n8n-nodes-base": "~1.1.1", | ||||||
|     "gulp": "^4.0.2", |     "gulp": "^4.0.2", | ||||||
|     "n8n-core": "~0.122.1", |     "n8n-core": "^0.124.0", | ||||||
|     "n8n-workflow": "~0.104.0", |     "n8n-workflow": "^0.106.0", | ||||||
|     "prettier": "^2.7.1", |     "prettier": "^2.7.1", | ||||||
|     "tslint": "^6.1.2", |     "tslint": "^6.1.2", | ||||||
|     "typescript": "~4.6.0" |     "typescript": "~4.6.0" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue