From 4bde05f41737ae37ba0e3bc7e74fea82f86a8451 Mon Sep 17 00:00:00 2001 From: Matheus Cansian Date: Sat, 5 Oct 2019 12:03:18 -0300 Subject: [PATCH] Implement node for AWS Lambda --- .../nodes-base/nodes/Aws/AwsLambda.node.ts | 145 ++++++++++++++++++ packages/nodes-base/nodes/Aws/lambda.png | Bin 0 -> 11484 bytes 2 files changed, 145 insertions(+) create mode 100644 packages/nodes-base/nodes/Aws/AwsLambda.node.ts create mode 100644 packages/nodes-base/nodes/Aws/lambda.png diff --git a/packages/nodes-base/nodes/Aws/AwsLambda.node.ts b/packages/nodes-base/nodes/Aws/AwsLambda.node.ts new file mode 100644 index 0000000000..bcbbca63a2 --- /dev/null +++ b/packages/nodes-base/nodes/Aws/AwsLambda.node.ts @@ -0,0 +1,145 @@ +import { IExecuteFunctions } from 'n8n-core'; +import { + INodeTypeDescription, + INodeExecutionData, + INodeType, + INodePropertyOptions, + ILoadOptionsFunctions, + IDataObject +} from 'n8n-workflow'; + +import { awsConfigCredentials } from './GenericFunctions'; + +import { Lambda } from 'aws-sdk'; + +export class AwsLambda implements INodeType { + description: INodeTypeDescription = { + displayName: 'AWS Lambda', + name: 'awsLambda', + icon: 'file:lambda.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["function"]}}', + description: 'Invoke functions on AWS Lambda', + defaults: { + name: 'AWS Lambda', + color: '#FF9900', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'aws', + required: true, + } + ], + properties: [ + { + displayName: 'Function', + name: 'function', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getFunctions', + }, + options: [], + default: '', + required: true, + description: 'The function you want to invoke', + }, + { + displayName: 'Qualifier', + name: 'qualifier', + type: 'string', + required: true, + default: '$LATEST', + description: 'Specify a version or alias to invoke a published version of the function', + }, + { + displayName: 'Invocation Type', + name: 'invocationType', + type: 'options', + options: [ + { + name: 'Wait for results', + value: 'RequestResponse', + description: 'Invoke the function synchronously and wait for the response', + }, + { + name: 'Continue workflow', + value: 'Event', + description: 'Invoke the function and immediately continue the workflow', + }, + ], + default: 'RequestResponse', + description: 'Specify if the workflow should wait for the function to return the results', + }, + { + displayName: 'JSON Input', + name: 'payload', + type: 'string', + default: '', + description: 'The JSON that you want to provide to your Lambda function as input', + typeOptions: { + alwaysOpenEditWindow: true, + }, + }, + ], + }; + + methods = { + loadOptions: { + async getFunctions(this: ILoadOptionsFunctions): Promise { + await awsConfigCredentials.call(this); + + const returnData: INodePropertyOptions[] = []; + + let lambda = new Lambda(); + try { + var data = await lambda.listFunctions({}).promise(); + } catch (err) { + throw new Error(`AWS Error: ${err}`); + } + + for (let func of data.Functions!) { + returnData.push({ + name: func.FunctionName as string, + value: func.FunctionArn as string, + }); + } + return returnData; + } + }, + }; + + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + + await awsConfigCredentials.call(this); + const lambda = new Lambda(); + + for (let i = 0; i < items.length; i++) { + const params = { + FunctionName: this.getNodeParameter('function', i) as string, + InvocationType: this.getNodeParameter('invocationType', i) as string, + Payload: this.getNodeParameter('payload', i) as string, + Qualifier: this.getNodeParameter('qualifier', i) as string, + }; + + try { + var responseData = await lambda.invoke(params).promise(); + } catch (err) { + throw new Error(`AWS Error: ${err}`); + } + + returnData.push({ + StatusCode: responseData.StatusCode, + Result: responseData.Payload, + Error: responseData.FunctionError, + } as IDataObject); + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/Aws/lambda.png b/packages/nodes-base/nodes/Aws/lambda.png new file mode 100644 index 0000000000000000000000000000000000000000..d98d8f3cdc7155a79afe72174ee41d215023575b GIT binary patch literal 11484 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