Skip to content

docs(commons): refresh API docs & README #2452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 82 additions & 63 deletions packages/commons/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,96 @@ Powertools for AWS Lambda (TypeScript) is a developer toolkit to implement Serve

You can use the library in both TypeScript and JavaScript code bases.

> Also available in [Python](https://github.com/aws-powertools/powertools-lambda-python), [Java](https://github.com/aws-powertools/powertools-lambda-java), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet).
## Intro

**[Documentation](https://docs.powertools.aws.dev/lambda/typescript/)** | **[npm](https://www.npmjs.com/org/aws-lambda-powertools)** | **[Roadmap](https://docs.powertools.aws.dev/lambda/typescript/latest/roadmap)** | **[Examples](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples)**
The Commons package contains a set of utilities that are shared across one or more Powertools for AWS Lambda (TypeScript) utilities. Some of these utilities can also be used independently in your AWS Lambda functions.

## Table of contents <!--- omit in toc -->
## Usage

- [Table of contents ](#table-of-contents-)
- [Features](#features)
- [Getting started](#getting-started)
- [Installation](#installation)
- [Examples](#examples)
- [Demo applications](#demo-applications)
- [Contribute](#contribute)
- [Roadmap](#roadmap)
- [Connect](#connect)
- [How to support Powertools for AWS Lambda (TypeScript)?](#how-to-support-powertools-for-aws-lambda-typescript)
- [Becoming a reference customer](#becoming-a-reference-customer)
- [Sharing your work](#sharing-your-work)
- [Using Lambda Layer](#using-lambda-layer)
- [Credits](#credits)
- [License](#license)
To get started, install the utility by running:

## Features

* **[Tracer](https://docs.powertools.aws.dev/lambda/typescript/latest/core/tracer/)** - Utilities to trace Lambda function handlers, and both synchronous and asynchronous functions
* **[Logger](https://docs.powertools.aws.dev/lambda/typescript/latest/core/logger/)** - Structured logging made easier, and a middleware to enrich log items with key details of the Lambda context
* **[Metrics](https://docs.powertools.aws.dev/lambda/typescript/latest/core/metrics/)** - Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF)
* **[Parameters](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/)** - High-level functions to retrieve one or more parameters from AWS SSM, Secrets Manager, AppConfig, and DynamoDB
* **[Idempotency](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/idempotency/)** - Class method decorator, Middy middleware, and function wrapper to make your Lambda functions idempotent and prevent duplicate execution based on payload content
* **[Batch processing](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/batch/)** - Utility to handle partial failures when processing batches from Amazon SQS, Amazon Kinesis Data Streams, and Amazon DynamoDB Streams.
```sh
npm i @aws-lambda-powertools/commons
```

## Getting started
### Type utils

Find the complete project's [documentation here](https://docs.powertools.aws.dev/lambda/typescript).
When working with different objects and values, you may want to do runtime type checks. The utility comes with a set of type utilities that you can use to check the type of an object or value.

### Installation
```typescript
import { isRecord } from '@aws-lambda-powertools/commons/typeUtils';
import { isString } from '@aws-lambda-powertools/commons/typeUtils';
import { isTruthy } from '@aws-lambda-powertools/commons/typeUtils';

The Powertools for AWS Lambda (TypeScript) utilities follow a modular approach, similar to the official [AWS SDK v3 for JavaScript](https://github.com/aws/aws-sdk-js-v3).

Each TypeScript utility is installed as standalone npm package.
const value = { key: 'value' };
if (isRecord(value)) {
// value is a record
}

Install all three core utilities at once with this single command:
const stringValue = 'string';
if (isString(stringValue)) {
// stringValue is a string
}

```shell
npm install @aws-lambda-powertools/logger @aws-lambda-powertools/tracer @aws-lambda-powertools/metrics
const truthyValue = 'true';
if (isTruthy(truthyValue)) {
// truthyValue is truthy
}
```

Or refer to the installation guide of each utility:
Here's a full list of type utilities available in the package:

- [`isInteger`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isIntegerNumber.html)
- [`isNull`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isNull.html)
- [`isNullOrUndefined`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isNullOrUndefined.html)
- [`isNumber`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isNumber.html)
- [`isRecord`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isRecord.html)
- [`isStrictEqual`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isStrictEqual.html)
- [`isString`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isString.html)
- [`isTruthy`](https://docs.powertools.aws.dev/lambda/typescript/latest/api/functions/_aws_lambda_powertools_commons.isTruthy.html)

Many of these utilities also double as type guards, which you can use to narrow down the type of an object or value.

### Base64 utils

When working with Base64-encoded data, you can use the `fromBase64` utilities to quickly decode data and convert it to a `Uint8Array`.

```typescript

👉 [Installation guide for the **Tracer** utility](https://docs.powertools.aws.dev/lambda/typescript/latest/core/tracer#getting-started)
import { fromBase64 } from '@aws-lambda-powertools/commons/utils/base64';

👉 [Installation guide for the **Logger** utility](https://docs.powertools.aws.dev/lambda/typescript/latest/core/logger#getting-started)
const encodedValue = 'aGVsbG8gd29ybGQ=';

👉 [Installation guide for the **Metrics** utility](https://docs.powertools.aws.dev/lambda/typescript/latest/core/metrics#getting-started)
const decoded = fromBase64(encodedValue);
// new Uint8Array([ 97, 71, 86, 115, 98, 71, 56, 103, 100, 50, 57, 121, 98, 71, 81, 61 ]);
```

### JSON type utils

👉 [Installation guide for the **Parameters** utility](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/#getting-started)
In some cases, you may want to define a type for a JSON object or value. The utility comes with a set of types that you can use to define your JSON objects.

### Examples
```typescript
import type { JSONValue, JSONObject, JSONArray } from '@aws-lambda-powertools/commons';
```

You can find examples of how to use Powertools for AWS Lambda (TypeScript) in the [examples](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/app) directory. The application is a simple REST API that can be deployed via either AWS CDK or AWS SAM.
### Lambda interface

### Demo applications
When using object-oriented patterns to define your Lambda handlers, you can use the `LambdaHandler` interface to define the shape of your handler methods.

The [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) shows how to use Powertools for AWS Lambda (TypeScript).
You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo).
```typescript
import type { Context } from 'aws-lambda';
import type { LambdaInterface } from '@aws-lambda-powertools/commons/types';

The [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository also uses Powertools for AWS Lambda (TypeScript) as well as demonstrating other performance tuning techniques for Lambda functions written in TypeScript.
class Lambda implements LambdaInterface {
public handler = async (event: unknown, context: Context) => {
// Your handler code here
}
}

const handlerClass = new Lambda();
export const handler = lambda.handler.bind(lambda);
```

## Contribute

Expand All @@ -83,8 +106,8 @@ Help us prioritize upcoming functionalities or utilities by [upvoting existing R

## Connect

* **Powertools for AWS Lambda on Discord**: `#typescript` - **[Invite link](https://discord.gg/B8zZKbbyET)**
* **Email**: [email protected]
- **Powertools for AWS Lambda on Discord**: `#typescript` - **[Invite link](https://discord.gg/B8zZKbbyET)**
- **Email**: <[email protected]>

## How to support Powertools for AWS Lambda (TypeScript)?

Expand All @@ -94,29 +117,25 @@ Knowing which companies are using this library is important to help prioritize t

The following companies, among others, use Powertools:

* [Hashnode](https://hashnode.com/)
* [Trek10](https://www.trek10.com/)
* [Elva](https://elva-group.com)
* [globaldatanet](https://globaldatanet.com/)
* [Bailey Nelson](https://www.baileynelson.com.au)
* [Perfect Post](https://www.perfectpost.fr)
* [Sennder](https://sennder.com/)
* [Certible](https://www.certible.com/)
* [tecRacer GmbH & Co. KG](https://www.tecracer.com/)
* [AppYourself](https://appyourself.net)
* [Alma Media](https://www.almamedia.fi)
- [Hashnode](https://hashnode.com/)
- [Trek10](https://www.trek10.com/)
- [Elva](https://elva-group.com)
- [globaldatanet](https://globaldatanet.com/)
- [Bailey Nelson](https://www.baileynelson.com.au)
- [Perfect Post](https://www.perfectpost.fr)
- [Sennder](https://sennder.com/)
- [Certible](https://www.certible.com/)
- [tecRacer GmbH & Co. KG](https://www.tecracer.com/)
- [AppYourself](https://appyourself.net)
- [Alma Media](https://www.almamedia.fi)

### Sharing your work

Share what you did with Powertools for AWS Lambda (TypeScript) 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools for AWS Lambda (TypeScript) [here](https://docs.powertools.aws.dev/lambda/typescript/latest/we_made_this).

### Using Lambda Layer

This helps us understand who uses Powertools for AWS Lambda (TypeScript) in a non-intrusive way, and helps us gain future investments for other Powertools for AWS Lambda languages. When [using Layers](#lambda-layers), you can add Powertools for AWS Lambda (TypeScript) as a dev dependency (or as part of your virtual env) to not impact the development process.

## Credits

Credits for the Lambda Powertools for AWS Lambda (TypeScript) idea go to [DAZN](https://github.com/getndazn) and their [DAZN Lambda Powertools](https://github.com/getndazn/dazn-lambda-powertools/).
This helps us understand who uses Powertools for AWS Lambda (TypeScript) in a non-intrusive way, and helps us gain future investments for other Powertools for AWS Lambda languages. When [using Layers](https://docs.powertools.aws.dev/lambda/typescript/latest/#lambda-layer), you can add Powertools as a dev dependency to not impact the development process.

## License

Expand Down
52 changes: 39 additions & 13 deletions packages/commons/src/Utility.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/**
* ## Intro
* Utility is a base class that other Powertools for AWS Lambda (TypeScript) utilites can extend to inherit shared logic.
* `Utility` is a base class that other Powertools for AWS Lambda (TypeScript) utilites can extend to inherit shared logic.
*
* Its main purpose is to encapsulate the cold start heuristic logic. Cold start is a term commonly used to describe the `Init` phase of a Lambda function.
* In this phase, Lambda creates or unfreezes an execution environment with the configured resources, downloads the code for the function and all layers,
* initializes any extensions, initializes the runtime, and then runs the function’s initialization code (the code outside the main handler).
*
* ## Key features
* * Cold Start heuristic to determine if the current
*
* ## Usage
*
* ### Cold Start
*
* Cold start is a term commonly used to describe the `Init` phase of a Lambda function. In this phase, Lambda creates or unfreezes an execution environment with the configured resources, downloads the code for the function and all layers, initializes any extensions, initializes the runtime, and then runs the function’s initialization code (the code outside the main handler). The Init phase happens either during the first invocation, or in advance of function invocations if you have enabled provisioned concurrency.
* The Init phase happens either during the first invocation, or in advance of function invocations if you have enabled provisioned concurrency.
*
* To learn more about the Lambda execution environment lifecycle, see the [Execution environment section](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) of the AWS Lambda documentation.
*
Expand All @@ -21,7 +16,7 @@
*
* If you want to use this logic in your own utilities, `Utility` provides two methods:
*
* #### `getColdStart()`
* `Utility.getColdStart()`
*
* Since the `Utility` class is instantiated outside of the Lambda handler it will persist across invocations of the same execution environment. This means that if you call `getColdStart()` multiple times, it will return `true` during the first invocation, and `false` afterwards.
*
Expand All @@ -36,7 +31,7 @@
* };
* ```
*
* #### `isColdStart()`
* `Utility.isColdStart()`
*
* This method is an alias of `getColdStart()` and is exposed for convenience and better readability in certain usages.
*
Expand All @@ -59,6 +54,20 @@ export class Utility {
private coldStart = true;
private readonly defaultServiceName: string = 'service_undefined';

/**
* Get the cold start status of the current execution environment.
*
* @example
* ```typescript
* import { Utility } from '@aws-lambda-powertools/commons';
*
* const utility = new Utility();
* utility.isColdStart(); // true
* utility.isColdStart(); // false
* ```
*
* The method also flips the cold start status to `false` after the first invocation.
*/
public getColdStart(): boolean {
if (this.coldStart) {
this.coldStart = false;
Expand All @@ -69,10 +78,27 @@ export class Utility {
return false;
}

/**
* Get the cold start status of the current execution environment.
*
* @example
* ```typescript
* import { Utility } from '@aws-lambda-powertools/commons';
*
* const utility = new Utility();
* utility.isColdStart(); // true
* utility.isColdStart(); // false
* ```
*
* @see {@link getColdStart}
*/
public isColdStart(): boolean {
return this.getColdStart();
}

/**
* Get the default service name.
*/
protected getDefaultServiceName(): string {
return this.defaultServiceName;
}
Expand All @@ -81,7 +107,7 @@ export class Utility {
* Validate that the service name provided is valid.
* Used internally during initialization.
*
* @param serviceName - Service name to validate
* @param serviceName Service name to validate
*/
protected isValidServiceName(serviceName?: string): boolean {
return typeof serviceName === 'string' && serviceName.trim().length > 0;
Expand Down
33 changes: 26 additions & 7 deletions packages/commons/src/awsSdkUtils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { PT_VERSION } from './version.js';
import type { MiddlewareArgsLike, SdkClient } from './types/awsSdk.js';

/**
* @internal
*/
const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA';
const middlewareOptions = {
relation: 'after',
Expand All @@ -13,8 +10,9 @@ const middlewareOptions = {
};

/**
* Type guard to check if the client provided is a valid AWS SDK v3 client.
*
* @internal
* Type guard to check if the client provided is a valid AWS SDK v3 client
*/
const isSdkClient = (client: unknown): client is SdkClient =>
typeof client === 'object' &&
Expand All @@ -35,9 +33,16 @@ const isSdkClient = (client: unknown): client is SdkClient =>
typeof client.middlewareStack.addRelativeTo === 'function';

/**
* Helper function to create a custom user agent middleware for the AWS SDK v3 clients.
*
* The middleware will append the provided feature name and the current version of
* the Powertools for AWS Lambda library to the user agent string.
*
* @example "PT/Tracer/2.1.0 PTEnv/nodejs20x"
*
* @param feature The feature name to be added to the user agent
*
* @internal
* returns a middleware function for the MiddlewareStack, that can be used for the SDK clients
* @param feature
*/
const customUserAgentMiddleware = (feature: string) => {
return <T extends MiddlewareArgsLike>(next: (arg0: T) => Promise<T>) =>
Expand All @@ -51,8 +56,12 @@ const customUserAgentMiddleware = (feature: string) => {
};

/**
* Check if the provided middleware stack already has the Powertools for AWS Lambda
* user agent middleware.
*
* @param middlewareStack The middleware stack to check
*
* @internal
* Checks if the middleware stack already has the Powertools UA middleware
*/
const hasPowertools = (middlewareStack: string[]): boolean => {
let found = false;
Expand All @@ -65,6 +74,16 @@ const hasPowertools = (middlewareStack: string[]): boolean => {
return found;
};

/**
* Add the Powertools for AWS Lambda user agent middleware to the
* AWS SDK v3 client provided.
*
* We use this middleware to unbotrusively track the usage of the library
* and secure continued investment in the project.
*
* @param client The AWS SDK v3 client to add the middleware to
* @param feature The feature name to be added to the user agent
*/
const addUserAgentMiddleware = (client: unknown, feature: string): void => {
try {
if (isSdkClient(client)) {
Expand Down
Loading