import { Construct } from 'constructs'; import { ITable } from 'aws-cdk-lib/aws-dynamodb'; import { Rule } from 'aws-cdk-lib/aws-events'; import { LambdaIntegrationOptions, MethodOptions } from 'aws-cdk-lib/aws-apigateway'; import { LogGroupProps, ILogGroup } from 'aws-cdk-lib/aws-logs'; import { IRole, RoleProps, PrincipalBase, Policy, PolicyProps } from 'aws-cdk-lib/aws-iam'; import { Function as BaseLambda, FunctionProps, Permission, Code, IEventSource, LayerVersion } from 'aws-cdk-lib/aws-lambda'; import { LogLevel } from '../../lib/Logger'; import { Mutable } from '../../lib/Mutable'; import { HttpMethod } from '../../lib/HttpMethod'; import { Api } from './Api'; import { Tables } from './Tables'; export interface ApiEvent { method: HttpMethod; path: string; options?: Mutable; } export interface LambdaProps extends Mutable>, Mutable>, Mutable>, Mutable> { /** * Code to use with the lambda. Can pass a string to the absolute path of the code folder and the AssetCode * will be created for you. You can also pass in any Construct that extends Code * ie. InlineCode, AssetCode, S3Code, etc. */ code: string | Code; /** * The name of the resources to make. Generally this is a few short words. When passing `prefix` and * `name` the physical name of resources will take the format of `${prefix}-${name}`. If just name is passed * they will just be the value of `name` */ name: string; /** * The prefix to use for the resources. Will prefix all resource names with this value. For more info, see * [Naming](https://full-stack-pattern.matthewkeil.com/docs/naming) */ prefix?: string; /** * Option to not use fixed logicalId's for the RestApi resource. For more * info, see [Naming](https://full-stack-pattern.matthewkeil.com/docs/naming) * * @default false (resources will have their logicalId's set by the library and not cdk) */ dontOverrideLogicalId?: boolean; /** * LayerVersions to use with the lambda. Can pass in a strings, that are absolute path to the layer folder, * and the AssetCode will be made for the directory. Can also pass in an array of LayerVersion constructs. */ layers?: (LayerVersion | string)[]; /** * The IRole or arn of the service role. If a LambdaProps.role is passed no IAM will be created */ role?: IRole | string; /** * Array of principals that can invoke the lambda. Can pass a string arn, an IRole, or any Principal construct * and will create the AWS::Lambda::Permission for you. */ canInvoke?: (PrincipalBase | IRole | string)[]; /** * simplifies warming the function. Timing will be base by the Rule that gets * passed. Event will emit the { warmer: true } object to the function * * code can easily check for warming event and return early */ warmingEvent?: Rule; /** * Adds process.env.LOGGING_LEVEL to the lambda environment. Can be set to: * 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL' */ loggingLevel?: LogLevel; /** * Similar to the underlying LambdaProps.events but adds support for the * ApiEvent from this library. Works in conjunction with the Api construct. * * ApiEvents will build a dev server that can be run locally through the use * of [convert-lambda-to-express](https://www.npmjs.com/package/convert-lambda-to-express) library * * See [convert-lambda-to-express](https://www.npmjs.com/package/convert-lambda-to-express) for more information about * how to use this feature. */ events?: (IEventSource | ApiEvent)[]; /** * The Api to use with all ApiEvents. If no api is passed it looks at * Stack.of(this).node.tryFindChild('Api') base stack and will use the first * RestApi it finds if one exists. If no api is passed to the constructor, * nor is there a RestApi resource in the stack, one will be created. It will * be built so all subsequent Lambdas will be able to find and use the same api. */ api?: Api; /** * Handy feature to plug into existing logGroups. Pass an array of strings * that are the logGroup names in the target account and any log groups that * exist will not be created. ie no thrown errors, and stack rollbacks, for * log groups that exist */ existingLogGroups?: string[]; /** * Associates a table with the lambda function. Can be passed as a Table or * a string. When using a string must also pass a Tables object to the * `tables` prop. This is mostly a convention for use with the Lambdas and * Tables constructs so its easier to created the lambda definitions. See * the LambdasProps.tables for more information. */ table?: ITable | string; /** * Tables construct to make use of LambdaProps.table as a string. Will do * a lookup to find the table from the tables object using the string as the * name */ tables?: Tables; /** * By default, this construct sets the tableName to the environment for you. * * If a name of 'good-stuff-table' is used, will set environment variables as: * - `process.env.TABLE_NAME = "full-table-name-for-sdk"` * - `process.env.GOOD_STUFF_TABLE = "full-table-name-for-sdk"` * * You can override this with `tableEnvKey: "SOME_ENV_KEY"` to create the * environment variables as: * - `process.env.TABLE_NAME = "full-table-name-for-sdk"` * - `process.env.SOME_ENV_KEY = "full-table-name-for-sdk"` */ tableEnvKey?: string; } /** * Creates and configures */ export declare class Lambda extends Construct { readonly props: LambdaProps; function: BaseLambda; logGroup: ILogGroup; role: IRole; policy?: Policy; api?: Api; code: Code; private pascalName; private kebabName; constructor(scope: Construct, id: string, props: LambdaProps); /** * simplifies the underlying `lambda.Function.prototype.addPermission` * * - adds ability to just pass and arn as a string. automatically sets up * the principal * - adds the invoke action */ addPermission(principalOrArn: PrincipalBase | string, permission?: Partial): this; /** * simplifies warming the function. Timing will be base by the Rule that gets * passed. Event will emit the { warmer: true } object to the function * * code can easily check for warming event and return early */ addWarmingEvent(rule: Rule): this; /** * - adds an api event to the lambda: hooks up apiGateway to trigger the lambda * and adds the necessary permissions. * * - builds an express server to server the lambdas during development. devServer * supports hot reload and watch functionality. see [convert-lambda-to-express](https://www.npmjs.com/package/convert-lambda-to-express) * for more information * * - can, optionally, pass in the RestApi that you want associated to the function * through the LambdaProps.api property when new'ing the Lambda. If no api is * passed it looks at Stack.of(this).node.tryFindChild('Api') base stack and will * use the first RestApi it finds if one exists. If no api is passed to the * constructor, nor is there a RestApi resource in the stack, one will be * created. It will be built so all subsequent Lambdas will be able to find * and use the same api. * * If api is looked up then it can be anywhere in your code as long as its built * before trying to add an ApiEvent. Note that building the Lambda with an event in * the constructor props will call the .addApiEvent method under the hood. The * logicalId for the lookup method must be 'Api'. * * If you want to use a different Api logicalId, you can pass in the Api object * directly to the constructor */ addApiEvent(pathConfig: ApiEvent): Lambda; /** * Applies table.grantReadWriteData(role) for the function role if one was created. * * Adds table name to environment variables. As an example when passing in * `table: "good-stuff-table"` will, by default, set actual tableName as: * - `process.env.TABLE_NAME=client-project-env-good-stuff-table` * - `process.env.GOOD_STUFF_TABLE=client-project-env-good-stuff-table` * * You can override this with `tableEnvKey: TABLE_ENV_KEY` to create the * environment variables as: * `process.env.TABLE_NAME` * `process.env.TABLE_ENV_KEY` */ associateTable({ table, tables, tableEnvKey }: Pick): this; private _associateTable; private _buildIam; private _filterApiEvents; private _getApi; private _addApiEvent; }