async function invokeLambdaHandler()

in src/shared/sam/localLambdaRunner.ts [187:326]


async function invokeLambdaHandler(
    timer: Timeout,
    env: NodeJS.ProcessEnv,
    config: SamLaunchRequestArgs
): Promise<boolean> {
    getLogger('channel').info(localize('AWS.output.starting.sam.app.locally', 'Starting SAM application locally'))
    getLogger().debug(`localLambdaRunner.invokeLambdaFunction: ${config.name}`)

    const debugPort = !config.noDebug ? config.debugPort?.toString() : undefined

    if (config.invokeTarget.target === 'api') {
        // sam local start-api ...
        const samCliContext = new DefaultSamCliProcessInvokerContext()
        const sam = await samCliContext.cliConfig.getOrDetectSamCli()
        if (!sam.path) {
            getLogger().warn('SAM CLI not found and not configured')
        } else if (sam.autoDetected) {
            getLogger().info('SAM CLI not configured, using SAM found at: %O', sam.path)
        }
        const samCommand = sam.path ? sam.path : 'sam'
        const samArgs = await buildSamCliStartApiArguments({
            templatePath: config.templatePath,
            dockerNetwork: config.sam?.dockerNetwork,
            environmentVariablePath: config.envFile,
            environmentVariables: env,
            port: config.apiPort?.toString(),
            debugPort: debugPort,
            debuggerPath: config.debuggerPath,
            debugArgs: config.debugArgs,
            skipPullImage: config.sam?.skipNewImageCheck,
            parameterOverrides: config.parameterOverrides,
            containerEnvFile: config.containerEnvFile,
            extraArgs: config.sam?.localArguments,
            name: config.name,
        })

        const recordApigwTelemetry = (result: telemetry.Result) => {
            telemetry.recordApigatewayInvokeLocal({
                result: result,
                runtime: config.runtime as telemetry.Runtime,
                debug: !config.noDebug,
                httpMethod: config.api?.httpMethod,
                architecture: config.architecture,
            })
        }

        // We want async behavior so `await` is intentionally not used here, we
        // need to call requestLocalApi() while it is up.
        samStartApi = new Promise(resolve => {
            config
                .samLocalInvokeCommand!.invoke({
                    options: {
                        env: {
                            ...process.env,
                            ...env,
                        },
                    },
                    command: samCommand,
                    args: samArgs,
                    // "sam local start-api" produces "attach" messages similar to "sam local invoke".
                    waitForCues: true,
                    timeout: timer,
                    name: config.name,
                })
                .then(sam => {
                    recordApigwTelemetry('Succeeded')
                    samStartApiProc = sam
                    resolve(true)
                })
                .catch(e => {
                    recordApigwTelemetry('Failed')
                    getLogger().warn(e as Error)
                    getLogger('channel').error(
                        localize(
                            'AWS.error.during.apig.local',
                            'Failed to start local API Gateway: {0}',
                            (e as Error).message
                        )
                    )
                    resolve(false)
                })
        })

        return true
    } else {
        // 'target=code' or 'target=template'
        const localInvokeArgs: SamCliLocalInvokeInvocationArguments = {
            templateResourceName: makeResourceName(config),
            templatePath: config.templatePath,
            eventPath: config.eventPayloadFile,
            environmentVariablePath: config.envFile,
            environmentVariables: env,
            invoker: config.samLocalInvokeCommand!,
            dockerNetwork: config.sam?.dockerNetwork,
            debugPort: debugPort,
            debuggerPath: config.debuggerPath,
            debugArgs: config.debugArgs,
            containerEnvFile: config.containerEnvFile,
            extraArgs: config.sam?.localArguments,
            skipPullImage: config.sam?.skipNewImageCheck ?? (isImageLambdaConfig(config) || config.sam?.containerBuild),
            parameterOverrides: config.parameterOverrides,
            name: config.name,
        }

        // sam local invoke ...
        const command = new SamCliLocalInvokeInvocation(localInvokeArgs)
        let samVersion: string | undefined
        let invokeResult: telemetry.Result = 'Failed'

        try {
            samVersion = await getSamCliVersion(getSamCliContext())
            await command.execute(timer)
            invokeResult = 'Succeeded'
        } catch (err) {
            getLogger('channel').error(
                localize(
                    'AWS.error.during.sam.local',
                    'Failed to run SAM application locally: {0}',
                    (err as Error).message
                )
            )

            return false
        } finally {
            if (config.sam?.buildDir === undefined) {
                await remove(config.templatePath)
            }
            telemetry.recordLambdaInvokeLocal({
                lambdaPackageType: isImageLambdaConfig(config) ? 'Image' : 'Zip',
                result: invokeResult,
                runtime: config.runtime as telemetry.Runtime,
                debug: !config.noDebug,
                version: samVersion,
                architecture: config.architecture,
            })
        }

        return true
    }
}