Skip to content

docs(maintenance): update examples to v2 #2242

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 10 commits into from
Mar 25, 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
23 changes: 3 additions & 20 deletions .github/boring-cyborg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,7 @@ labelPRBasedOnFilePath:
- docs/**/*
- mkdocs.yml
- typedoc.js
- examples/cdk/bin/*
- examples/cdk/functions/*
- examples/cdk/functions/**/*
- examples/cdk/src/*
- examples/cdk/src/**/*
- examples/cdk/tests/*
- examples/cdk/tests/**/*
- examples/cdk/README.md
- examples/cdk/cdk.json
- examples/sam/events/*
- examples/sam/src/*
- examples/sam/src/**/*
- examples/sam/tests/*
- examples/sam/tests/**/*
- examples/sam/README.md
- examples/sam/template.yaml
- examples/app/*

area/automation:
- .github/scripts/*
Expand Down Expand Up @@ -137,8 +122,7 @@ labelPRBasedOnFilePath:
- packages/parser/README.md
- layers/tsconfig*.json
- layers/README.md
- examples/sam/tsconfig*.json
- examples/cdk/tsconfig*.json
- examples/app/tsconfig*.json

type/dependencies:
- package.json
Expand All @@ -153,8 +137,7 @@ labelPRBasedOnFilePath:
- packages/validator/package.json
- packages/batch/package.json
- layers/package.json
- examples/cdk/package.json
- examples/sam/package.json
- examples/app/package.json

##### Greetings ########################################################################################################
firstPRWelcomeComment: >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
NODE_ENV: dev
strategy:
matrix:
example: ["sam", "cdk"]
example: ["app"]
fail-fast: false
defaults:
run:
Expand Down
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ site
# Generated API documentation (from TypeDoc)
/api

# SAM Example copies files
/examples/sam/src/handlers/*
!/examples/sam/src/handlers/COPY_LAMBDA_FUNCTIONS_HERE

# Layer temp files
tmp

Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ Or refer to the installation guide of each utility:

### Examples

* [CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk)
* [SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam)
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.

### Demo applications

Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Whenever possible, we use the same directory structure for all utilities. This m
There are also a few other workspaces that are not utilities published to npm, but that still share dependencies and/or runtime code with the utilities. These workspaces are:

* `docs/snippets`: contains the documentation code snippets
* `examples/*`: contains the example projects deployed via AWS CDK or AWS SAM
* `examples/app`: contains an example project that can be deployed via AWS CDK or AWS SAM
* `layers`: contains the code used to build and publish the [Lambda layers](../index.md#lambda-layer)

## Testing definition
Expand Down
7 changes: 2 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,9 @@ The examples in this documentation will feature all the approaches described abo

## Examples

The project's repository includes examples of how to instrument your functions both in AWS CDK and AWS SAM:
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){target="_blank"} directory. The application is a simple REST API that can be deployed via either AWS CDK or AWS SAM.

* [AWS CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk){target="_blank"}
* [AWS SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam){target="_blank"}

If instead you want to see Powertools for AWS Lambda (TypeScript) in a slightly more complex use case, check the [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) or the [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository. Both demos use Powertools for AWS Lambda (TypeScript) as well as demonstrating other common techniques for Lambda functions written in TypeScript.
If instead you want to see Powertools for AWS Lambda (TypeScript) in slightly different use cases, check the [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) or the [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository. Both demos use Powertools for AWS Lambda (TypeScript) as well as demonstrating other common techniques for Lambda functions written in TypeScript.


## Features
Expand Down
8 changes: 8 additions & 0 deletions examples/cdk/.gitignore → examples/app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@ node_modules
.cdk.staging
cdk.out
lib
# npm lock file - this is managed by the npm workspace
package-lock.json

**/.aws-sam

# SAM
samconfig.toml

# npm lock file - this is managed by the npm workspace
package-lock.json
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/cdk/cdk.json → examples/app/cdk.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"app": "npx ts-node --prefer-ts-exts bin/cdk-app.ts",
"app": "tsx cdk/example-app.ts",
"watch": {
"include": [
"**"
Expand Down
7 changes: 7 additions & 0 deletions examples/app/cdk/example-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env node
import 'source-map-support/register';
import { App } from 'aws-cdk-lib';
import { PowertoolsExampleStack } from './example-stack.js';

const app = new App();
new PowertoolsExampleStack(app, 'PowertoolsTypeScript-Example-CDK', {});
240 changes: 240 additions & 0 deletions examples/app/cdk/example-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import { RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
import { LambdaIntegration, RestApi } from 'aws-cdk-lib/aws-apigateway';
import {
AttributeType,
BillingMode,
StreamViewType,
Table,
TableClass,
} from 'aws-cdk-lib/aws-dynamodb';
import {
FilterCriteria,
FilterRule,
LayerVersion,
StartingPosition,
} from 'aws-cdk-lib/aws-lambda';
import { SqsDestination } from 'aws-cdk-lib/aws-lambda-destinations';
import { DynamoEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
import { OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Queue } from 'aws-cdk-lib/aws-sqs';
import { StringParameter } from 'aws-cdk-lib/aws-ssm';
import { Construct } from 'constructs';
import { FunctionWithLogGroup } from './function-with-logstream-construct.js';

export class PowertoolsExampleStack extends Stack {
public constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);

// Import Powertools layer to be used in some of the functions
const powertoolsLayer = LayerVersion.fromLayerVersionArn(
this,
'powertools-layer',
`arn:aws:lambda:${
Stack.of(this).region
}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:3`
);

// Items table
const itemsTable = new Table(this, 'items-table', {
tableName: 'powertools-example-items',
tableClass: TableClass.STANDARD_INFREQUENT_ACCESS,
billingMode: BillingMode.PAY_PER_REQUEST,
partitionKey: {
type: AttributeType.STRING,
name: 'id',
},
removalPolicy: RemovalPolicy.DESTROY,
stream: StreamViewType.NEW_IMAGE, // we use the stream to trigger the processItemsStreamFn
});

// Idempotency table
const idempotencyTable = new Table(this, 'idempotencyTable', {
tableName: 'powertools-example-idempotency',
partitionKey: {
name: 'id',
type: AttributeType.STRING,
},
timeToLiveAttribute: 'expiration',
billingMode: BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.DESTROY, // for demo only, change to RETAIN in production
});

/**
* We will store the idempotency table name in a SSM parameter to simulate a potential
* cross-stack reference. This is not strictly necessary in this example, but it's a good way of showing
* how to use SSM parameters and retrieve them using Powertools.
*/
const idempotencyTableNameParam = new StringParameter(
this,
'idempotency-table-name',
{
parameterName: '/items-store/idempotency-table-name',
stringValue: idempotencyTable.tableName,
}
);

/**
* In this example, we use ESM and bundle all the dependencies
* including the AWS SDK.
*
* Because we are using ESM and tree shake, we create an optimized bundle.
*/
const putItemFn = new FunctionWithLogGroup(this, 'put-item-fn', {
entry: './functions/put-item.ts',
functionName: 'powertools-example-put-item',
bundling: {
minify: true,
sourceMap: true,
keepNames: true,
format: OutputFormat.ESM,
sourcesContent: true,
mainFields: ['module', 'main'],
externalModules: [], // we bundle all the dependencies
esbuildArgs: {
'--tree-shaking': 'true',
},
// We include this polyfill to support `require` in ESM due to AWS X-Ray SDK for Node.js not being ESM compatible
banner:
'import { createRequire } from "module";const require = createRequire(import.meta.url);',
},
});
putItemFn.bindTable({ table: itemsTable, accessMode: 'RW' });
/**
* Allow the function to read and write to the idempotency table so it
* can persist idempotency data
*/
putItemFn.bindTable({
table: idempotencyTable,
accessOnly: true,
accessMode: 'RW',
});
/**
* Also allow the function to fetch the SSM parameter
* that contains the idempotency table name
*/
idempotencyTableNameParam.grantRead(putItemFn);
putItemFn.addEnvironment(
'SSM_PARAMETER_NAME',
idempotencyTableNameParam.parameterName
);

/**
* In this example, we instead use the Powertools layer to include Powertools
* as well as the AWS SDK, this is a convenient way to use Powertools
* in a centralized way across all your functions.
*/
const getAllItemsFn = new FunctionWithLogGroup(this, 'get-all-items-fn', {
entry: './functions/get-all-items.ts',
functionName: 'powertools-example-get-all-items',
layers: [powertoolsLayer], // we use the powertools layer
bundling: {
minify: true,
sourceMap: true,
keepNames: true,
format: OutputFormat.ESM,
mainFields: ['module', 'main'],
sourcesContent: true,
externalModules: ['@aws-sdk/*', '@aws-lambda-powertools/*'], // the dependencies are included in the layer
esbuildArgs: {
'--tree-shaking': 'true',
},
// We include this polyfill to support `require` in ESM due to AWS X-Ray SDK for Node.js not being ESM compatible
banner:
'import { createRequire } from "module";const require = createRequire(import.meta.url);',
},
});
getAllItemsFn.bindTable({ table: itemsTable });

/**
* In this examle, we emit a CommonJS (CJS) bundle and include all the
* dependencies in it.
*/
const getByIdFn = new FunctionWithLogGroup(this, 'get-by-id-fn', {
entry: './functions/get-by-id.ts',
functionName: 'powertools-example-get-by-id',
bundling: {
minify: true,
sourceMap: true,
keepNames: true,
format: OutputFormat.CJS,
mainFields: ['main'],
sourcesContent: true,
externalModules: [], // we bundle all the dependencies
},
});
getByIdFn.bindTable({ table: itemsTable });

/**
* In this example, we use the Powertools layer to include Powertools
* but we also bundle the function as CommonJS (CJS).
*/
const processItemsStreamFn = new FunctionWithLogGroup(
this,
'process-items-stream-fn',
{
entry: './functions/process-items-stream.ts',
functionName: 'powertools-example-process-items-stream',
layers: [powertoolsLayer],
bundling: {
minify: true,
sourceMap: true,
keepNames: true,
format: OutputFormat.CJS,
mainFields: ['main'],
sourcesContent: true,
externalModules: ['@aws-sdk/*', '@aws-lambda-powertools/*'], // the dependencies are included in the layer
},
}
);
// Dead letter queue for the items that fail to be processed after the retry attempts
const dlq = new Queue(this, 'dead-letter-queue', {
queueName: 'powertools-example-dead-letter-queue',
removalPolicy: RemovalPolicy.DESTROY,
});
// Add the DynamoDB event source to the function
processItemsStreamFn.addEventSource(
new DynamoEventSource(itemsTable, {
startingPosition: StartingPosition.LATEST,
reportBatchItemFailures: true, // Enable batch failure reporting
onFailure: new SqsDestination(dlq),
batchSize: 100,
retryAttempts: 3,
filters: [
// Filter by the INSERT event type and the presence of the id and name attributes
FilterCriteria.filter({
eventName: FilterRule.isEqual('INSERT'),
dynamodb: {
NewImage: {
id: {
S: FilterRule.exists(),
},
name: {
S: FilterRule.exists(),
},
},
},
}),
],
})
);

// Create an API Gateway to expose the items service
const api = new RestApi(this, 'items-api', {
restApiName: 'Items Service',
description: 'This service serves items.',
deployOptions: {
tracingEnabled: true,
},
});

const itemPutIntegration = new LambdaIntegration(putItemFn);
api.root.addMethod('POST', itemPutIntegration);

const itemsIntegration = new LambdaIntegration(getAllItemsFn);
api.root.addMethod('GET', itemsIntegration);

const item = api.root.addResource('{id}');
const itemIntegration = new LambdaIntegration(getByIdFn);
item.addMethod('GET', itemIntegration);
}
}
Loading