Как использовать TypeScript для AWS Lambda за 3 шага

Серия AWS Lambda / NodeJS (TypeScript)

  1. Как использовать TypeScript для AWS Lambda за 3 шага s
  2. Модульный тест и тест интеграции для AWS Lambda / NodeJS в TypeScript

Ситуация

Когда мы используем NodeJS в качестве среды выполнения для AWS Lambdas, JavaScript является языком по умолчанию. Однако из-за отсутствия проверки ввода в JavaScript время от времени ошибочный код развертывается в Lambda. Например, такая небольшая опечатка:

exports.lambdaHandler = async (event, context) => {

  const queries = event.queytStringParameters;

  // ...
}

Мы хотим получить queryStringParameters, но queries заканчивается undefined в результате невнимательности.

Цель

Мы хотим использовать TypeScript для написания обработчиков лямбда. С TypeScript у нас будут следующие преимущества:

  1. Подсказки автозавершения кода при программировании
  2. Проверка ошибок времени компиляции, чтобы избежать избыточных развертываний

Это несложно, в этой статье представлены 3 шага для выполнения этой работы.

Подготовка

Прежде чем пройти три шага, давайте создадим классический лямбда-проект с помощью SAM CLI:

sam init

После указанной выше команды мы получим папку с этими файлами:

├── README.md
├── events
│   └── event.json
├── hello-world
│   ├── app.js
│   ├── package.json
│   └── tests
│       └── unit
│           └── test-handler.js
└── template.yaml

Затем мы начнем переводить этот JS-пакет в TS-пакет.

Шаг 1. Добавьте зависимость TypeScript

В package.json добавьте следующие коды:

"scripts": {
  "compile": "tsc"
},
"devDependencies": {
  "aws-sdk": "^2.655.0",
  "@types/aws-lambda": "^8.10.51",
  "@types/node": "^13.13.5",
  "typescript": "^3.8.3"
}
  • scripts / compile: это будет использоваться для компиляции кода TypeScript в JavaScript.
  • devDependencies: поскольку это только для разработки, нам не нужно добавлять пакеты в блок dependencies
  • aws-sdk: в зависимости от того, используете ли вы AWS SDK в лямбда-выражении.
  • @ types / aws-lambda: это очень важно для проверки завершения кода и ввода.
  • @ types / node: нам нужен этот пакет для встроенных типов
  • машинописный текст: откуда tsc

Шаг 2. Добавьте tsconfig.json

{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES2017",
    "noImplicitAny": true,
    "preserveConstEnums": true,
    "outDir": "./built",
    "sourceMap": true
  },
  "include": ["src-ts/**/*"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

Компилятору TypeScript требуется tsconfig.json, чтобы понять, как преобразовать TypeScript в JavaScript.

  • модуль: CommonJS здесь подойдет
  • target: применение ES2017 сохранит синтаксис async и await вместо преобразования их в Promise код. Поскольку мы используем Node12 в качестве среды выполнения, функция Lambda поддерживает интерпретацию синтаксиса. Между тем, сохранение async и await делает код чистым и коротким.
  • noImplicitAny: рекомендуется иметь. Компилятор выдаст ошибку, если переменная объявлена ​​без типа
  • preserveConstEnums: больше похоже на синтаксический сахар, но я хотел бы оставить его включенным, потому что он может сохранять enum классы в коде JavaScript в форме object, что помогает понять код JavaScript.
  • outDir: любая папка, которую вы хотите установить в качестве вывода компиляции.
  • sourceMap: это необязательно

Шаг 3. Измените код

Сначала создайте папку src-ts и переместите app.js в эту папку.

app.js теперь выглядит так:

exports.lambdaHandler = async (event, context) => {
  const queries = JSON.stringify(event.queytStringParameters);
  return {
    statusCode: 200,
    body: `Queries: ${queries}`
  }
};

Создадим app.ts и заменим его:

import { 
  APIGatewayProxyEvent, 
  APIGatewayProxyResult 
} from "aws-lambda";
export const lambdaHandler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  const queries = JSON.stringify(event.queryStringParameters);
  return {
    statusCode: 200,
    body: `Queries: ${queries}`
  }
}

Поскольку этот файл TypeScript будет скомпилирован в папку built, нам также необходимо изменить поле Handler в template.yaml, чтобы ресурс lambda мог найти код по правильному пути:

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/built
      Handler: app.lambdaHandler

Мы добавляем путь built к папке hello-world, чтобы AWS Lambda могла правильно найти обработчик.

Теперь каталог выглядит так:

├── README.md
├── hello-world
│   ├── built
│   │   ├── app.js
│   │   └── app.js.map
│   ├── package-lock.json
│   ├── package.json
│   ├── src-ts
│   │   ├── app.ts
│   │   └── tests
│   └── tsconfig.json
├── samconfig.toml
└── template.yaml

Развертывание и тестирование

cd hello-world
npm install
npm run compile
cd ..
sam deploy --guided

После успешного развертывания мы увидим функцию Lambda в консоли AWS следующим образом:

И мы должны иметь возможность протестировать лямбда-функцию с помощью следующей команды:

▶ curl https://[API_ID].amazonaws.com/Prod/hello\?weather\=sunny
Queries: {"weather":"sunny"}

Заключение и следующий шаг

Пример кода можно найти по адресу: https://github.com/zijing07/aws-lambda-nodejs-ts

Я нахожу это действительно освежающим после использования поддержки TypeScript для моих функций Lambda. С одной стороны, это могло бы сэкономить мне массу времени на поиск в документации API имени метода или списка параметров. С другой стороны, tsc также помогает мне обнаруживать любые потенциальные проблемы перед развертыванием.

В следующей статье я расскажу о том, как проводить локальные интеграционные тесты на Lambda-функциях.