Skip to content

docs(validation): api docs & minor fixes #3713

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 12, 2025
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- markdownlint-disable MD013 -->
# Powertools for AWS Lambda (TypeScript) <!-- omit in toc -->

![NodeSupport](https://img.shields.io/static/v1?label=node&message=%2016|%2018|%2020&color=green?style=flat-square&logo=node)
![NodeSupport](https://img.shields.io/static/v1?label=node&message=%2018|%2020|%2022&color=green?style=flat-square&logo=node)
![GitHub Release](https://img.shields.io/github/v/release/aws-powertools/powertools-lambda-typescript?style=flat-square)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-typescript&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-typescript)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-typescript&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-typescript)
Expand All @@ -28,6 +28,7 @@ Find the complete project's [documentation here](https://docs.powertools.aws.dev
- **[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.
- **[JMESPath Functions](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/jmespath/)** - Built-in JMESPath functions to easily deserialize common encoded JSON payloads in Lambda functions.
- **[Parser (Zod)](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parser/)** - Utility that provides data validation and parsing using Zod, a TypeScript-first schema declaration and validation library.
- **[Validation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/validation/)** - JSON Schema validation for events and responses, including JMESPath support to unwrap events before validation.

## Install

Expand All @@ -41,6 +42,7 @@ You can use Powertools for AWS Lambda (TypeScript) by installing it with your fa
- **Batch**: `npm install @aws-lambda-powertools/batch`
- **JMESPath Functions**: `npm install @aws-lambda-powertools/jmespath`
- **Parser**: `npm install @aws-lambda-powertools/parser zod@~3`
- **Validation**: `npm install @aws-lambda-powertools/validation`

### Examples

Expand Down
221 changes: 216 additions & 5 deletions packages/validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

This utility provides JSON Schema validation for events and responses, including JMESPath support to unwrap events before validation.

> [!Warning]
> This feature is currently under development. As such it's considered not stable and we might make significant breaking changes before going before its release. You are welcome to [provide feedback](https://github.com/aws-powertools/powertools-lambda-typescript/discussions/3519) and [contribute to its implementation](https://github.com/aws-powertools/powertools-lambda-typescript/milestone/18).

Powertools for AWS Lambda (TypeScript) is a developer toolkit to implement Serverless [best practices and increase developer velocity](https://docs.powertools.aws.dev/lambda/typescript/latest/#features). You can use the library in both TypeScript and JavaScript code bases.

To get started, install the package by running:
Expand All @@ -13,8 +10,222 @@ To get started, install the package by running:
npm i @aws-lambda-powertools/validation
```

> [!Note]
> This readme is a work in progress.
## Features

You can validate inbound and outbound payloads using the `@validator` class method decorator or `validator` Middy.js middleware.

You can also use the standalone `validate` function, if you want more control over the validation process such as handling a validation error.

### Validator decorator

The `@validator` decorator is a TypeScript class method decorator that you can use to validate both the incoming event and the response payload.

If the validation fails, we will throw a `SchemaValidationError`.

```typescript
import { validator } from '@aws-lambda-powertools/validation/decorator';
import type { Context } from 'aws-lambda';

const inboundSchema = {
type: 'object',
properties: {
value: { type: 'number' },
},
required: ['value'],
additionalProperties: false,
};

const outboundSchema = {
type: 'object',
properties: {
result: { type: 'number' },
},
required: ['result'],
additionalProperties: false,
};

class Lambda {
@validator({
inboundSchema,
outboundSchema,
})
async handler(event: { value: number }, _context: Context) {
// Your handler logic here
return { result: event.value * 2 };
}
}

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

It's not mandatory to validate both the inbound and outbound payloads. You can either use one, the other, or both.

### Validator middleware

If you are using Middy.js, you can instead use the `validator` middleware to validate the incoming event and response payload.

```typescript
import { validator } from '@aws-lambda-powertools/validation/middleware';
import middy from '@middy/core';

const inboundSchema = {
type: 'object',
properties: {
foo: { type: 'string' },
},
required: ['foo'],
additionalProperties: false,
};

const outboundSchema = {
type: 'object',
properties: {
bar: { type: 'number' },
},
required: ['bar'],
additionalProperties: false,
};

export const handler = middy()
.use(validation({ inboundSchema, outboundSchema }))
.handler(async (event) => {
// Your handler logic here
return { bar: 42 };
});
```

Like the `@validator` decorator, you can choose to validate only the inbound or outbound payload.

### Standalone validate function

The `validate` function gives you more control over the validation process, and is typically used within the Lambda handler, or any other function that needs to validate data.

When using the standalone function, you can gracefully handle schema validation errors by catching `SchemaValidationError` errors.

```typescript
import { validate } from '@aws-lambda-powertools/validation';
import { SchemaValidationError } from '@aws-lambda-powertools/validation/errors';

const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
},
required: ['name', 'age'],
additionalProperties: false,
} as const;

const payload = { name: 'John', age: 30 };

export const handler = async (event: unknown) => {
try {
const validatedData = validate({
payload,
schema,
});

// Your handler logic here
} catch (error) {
if (error instanceof SchemaValidationError) {
// Handle the validation error
return {
statusCode: 400,
body: JSON.stringify({ message: error.message }),
};
}
// Handle other errors
throw error;
}
}
```

### JMESPath support

In some cases you might want to validate only a portion of the event payload - this is what the `envelope` option is for.

You can use JMESPath expressions to specify the path to the property you want to validate. The validator will unwrap the event before validating it.

```typescript
import { validate } from '@aws-lambda-powertools/validation';

const schema = {
type: 'object',
properties: {
user: { type: 'string' },
},
required: ['user'],
additionalProperties: false,
} as const;

const payload = {
data: {
user: 'Alice',
},
};

const validatedData = validate({
payload,
schema,
envelope: 'data',
});
```

### Extending the validator

Since the validator is built on top of [Ajv](https://ajv.js.org/), you can extend it with custom formats and external schemas, as well as bringing your own `ajv` instance.

The example below shows how to pass additional options to the `validate` function, but you can also pass them to the `@validator` decorator and `validator` middleware.

```typescript
import { validate } from '@aws-lambda-powertools/validation';

const formats = {
ageRange: (value: number) => return value >= 0 && value <= 120,
};

const definitionSchema = {
$id: 'https://example.com/schemas/definitions.json',
definitions: {
user: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number', format: 'ageRange' },
},
required: ['name', 'age'],
additionalProperties: false,
}
}
} as const;

const schema = {
$id: 'https://example.com/schemas/user.json',
type: 'object',
properties: {
user: { $ref: 'definitions.json#/definitions/user' },
},
required: ['user'],
additionalProperties: false,
} as const;

const payload = {
user: {
name: 'Alice',
age: 25,
},
};

const validatedData = validate({
payload,
schema,
externalRefs: [definitionSchema],
formats,
});
```

For more information on how to use the `validate` function, please refer to the [documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/validation).

## Contribute

Expand Down
41 changes: 35 additions & 6 deletions packages/validation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"name": "Amazon Web Services",
"url": "https://aws.amazon.com"
},
"private": true,
"scripts": {
"test": "vitest --run",
"test:unit": "vitest --run",
Expand All @@ -18,7 +17,7 @@
"test:e2e": "echo \"Not implemented\"",
"build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json",
"build:esm": "tsc --build tsconfig.esm.json && echo '{ \"type\": \"module\" }' > lib/esm/package.json",
"build": "echo \"Not implemented\"",
"build": "npm run build:esm & npm run build:cjs",
"lint": "biome lint .",
"lint:fix": "biome check --write .",
"prepack": "node ../../.github/scripts/release_patch_package_json.js ."
Expand All @@ -29,12 +28,42 @@
"exports": {
".": {
"require": {
"types": "./lib/cjs/index.d.ts",
"default": "./lib/cjs/index.js"
"types": "./lib/cjs/validate.d.ts",
"default": "./lib/cjs/validate.js"
},
"import": {
"types": "./lib/esm/index.d.ts",
"default": "./lib/esm/index.js"
"types": "./lib/esm/validate.d.ts",
"default": "./lib/esm/validate.js"
}
},
"./middleware": {
"require": {
"types": "./lib/cjs/middleware.d.ts",
"default": "./lib/cjs/middleware.js"
},
"import": {
"types": "./lib/esm/middleware.d.ts",
"default": "./lib/esm/middleware.js"
}
},
"./errors": {
"require": {
"types": "./lib/cjs/errors.d.ts",
"default": "./lib/cjs/errors.js"
},
"import": {
"types": "./lib/esm/errors.d.ts",
"default": "./lib/esm/errors.js"
}
},
"./decorator": {
"require": {
"types": "./lib/cjs/decorator.d.ts",
"default": "./lib/cjs/decorator.js"
},
"import": {
"types": "./lib/esm/decorator.d.ts",
"default": "./lib/esm/decorator.js"
}
}
},
Expand Down
Loading