Skip to content

Commit a0795fc

Browse files
authored
docs(validation): api docs & minor fixes (#3713)
1 parent 3973d38 commit a0795fc

16 files changed

+910
-177
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- markdownlint-disable MD013 -->
22
# Powertools for AWS Lambda (TypeScript) <!-- omit in toc -->
33

4-
![NodeSupport](https://img.shields.io/static/v1?label=node&message=%2016|%2018|%2020&color=green?style=flat-square&logo=node)
4+
![NodeSupport](https://img.shields.io/static/v1?label=node&message=%2018|%2020|%2022&color=green?style=flat-square&logo=node)
55
![GitHub Release](https://img.shields.io/github/v/release/aws-powertools/powertools-lambda-typescript?style=flat-square)
66
[![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)
77
[![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)
@@ -28,6 +28,7 @@ Find the complete project's [documentation here](https://docs.powertools.aws.dev
2828
- **[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.
2929
- **[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.
3030
- **[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.
31+
- **[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.
3132

3233
## Install
3334

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

4547
### Examples
4648

packages/validation/README.md

+216-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

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

5-
> [!Warning]
6-
> 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).
7-
85
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.
96

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

16-
> [!Note]
17-
> This readme is a work in progress.
13+
## Features
14+
15+
You can validate inbound and outbound payloads using the `@validator` class method decorator or `validator` Middy.js middleware.
16+
17+
You can also use the standalone `validate` function, if you want more control over the validation process such as handling a validation error.
18+
19+
### Validator decorator
20+
21+
The `@validator` decorator is a TypeScript class method decorator that you can use to validate both the incoming event and the response payload.
22+
23+
If the validation fails, we will throw a `SchemaValidationError`.
24+
25+
```typescript
26+
import { validator } from '@aws-lambda-powertools/validation/decorator';
27+
import type { Context } from 'aws-lambda';
28+
29+
const inboundSchema = {
30+
type: 'object',
31+
properties: {
32+
value: { type: 'number' },
33+
},
34+
required: ['value'],
35+
additionalProperties: false,
36+
};
37+
38+
const outboundSchema = {
39+
type: 'object',
40+
properties: {
41+
result: { type: 'number' },
42+
},
43+
required: ['result'],
44+
additionalProperties: false,
45+
};
46+
47+
class Lambda {
48+
@validator({
49+
inboundSchema,
50+
outboundSchema,
51+
})
52+
async handler(event: { value: number }, _context: Context) {
53+
// Your handler logic here
54+
return { result: event.value * 2 };
55+
}
56+
}
57+
58+
const lambda = new Lambda();
59+
export const handler = lambda.handler.bind(lambda);
60+
```
61+
62+
It's not mandatory to validate both the inbound and outbound payloads. You can either use one, the other, or both.
63+
64+
### Validator middleware
65+
66+
If you are using Middy.js, you can instead use the `validator` middleware to validate the incoming event and response payload.
67+
68+
```typescript
69+
import { validator } from '@aws-lambda-powertools/validation/middleware';
70+
import middy from '@middy/core';
71+
72+
const inboundSchema = {
73+
type: 'object',
74+
properties: {
75+
foo: { type: 'string' },
76+
},
77+
required: ['foo'],
78+
additionalProperties: false,
79+
};
80+
81+
const outboundSchema = {
82+
type: 'object',
83+
properties: {
84+
bar: { type: 'number' },
85+
},
86+
required: ['bar'],
87+
additionalProperties: false,
88+
};
89+
90+
export const handler = middy()
91+
.use(validation({ inboundSchema, outboundSchema }))
92+
.handler(async (event) => {
93+
// Your handler logic here
94+
return { bar: 42 };
95+
});
96+
```
97+
98+
Like the `@validator` decorator, you can choose to validate only the inbound or outbound payload.
99+
100+
### Standalone validate function
101+
102+
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.
103+
104+
When using the standalone function, you can gracefully handle schema validation errors by catching `SchemaValidationError` errors.
105+
106+
```typescript
107+
import { validate } from '@aws-lambda-powertools/validation';
108+
import { SchemaValidationError } from '@aws-lambda-powertools/validation/errors';
109+
110+
const schema = {
111+
type: 'object',
112+
properties: {
113+
name: { type: 'string' },
114+
age: { type: 'number' },
115+
},
116+
required: ['name', 'age'],
117+
additionalProperties: false,
118+
} as const;
119+
120+
const payload = { name: 'John', age: 30 };
121+
122+
export const handler = async (event: unknown) => {
123+
try {
124+
const validatedData = validate({
125+
payload,
126+
schema,
127+
});
128+
129+
// Your handler logic here
130+
} catch (error) {
131+
if (error instanceof SchemaValidationError) {
132+
// Handle the validation error
133+
return {
134+
statusCode: 400,
135+
body: JSON.stringify({ message: error.message }),
136+
};
137+
}
138+
// Handle other errors
139+
throw error;
140+
}
141+
}
142+
```
143+
144+
### JMESPath support
145+
146+
In some cases you might want to validate only a portion of the event payload - this is what the `envelope` option is for.
147+
148+
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.
149+
150+
```typescript
151+
import { validate } from '@aws-lambda-powertools/validation';
152+
153+
const schema = {
154+
type: 'object',
155+
properties: {
156+
user: { type: 'string' },
157+
},
158+
required: ['user'],
159+
additionalProperties: false,
160+
} as const;
161+
162+
const payload = {
163+
data: {
164+
user: 'Alice',
165+
},
166+
};
167+
168+
const validatedData = validate({
169+
payload,
170+
schema,
171+
envelope: 'data',
172+
});
173+
```
174+
175+
### Extending the validator
176+
177+
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.
178+
179+
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.
180+
181+
```typescript
182+
import { validate } from '@aws-lambda-powertools/validation';
183+
184+
const formats = {
185+
ageRange: (value: number) => return value >= 0 && value <= 120,
186+
};
187+
188+
const definitionSchema = {
189+
$id: 'https://example.com/schemas/definitions.json',
190+
definitions: {
191+
user: {
192+
type: 'object',
193+
properties: {
194+
name: { type: 'string' },
195+
age: { type: 'number', format: 'ageRange' },
196+
},
197+
required: ['name', 'age'],
198+
additionalProperties: false,
199+
}
200+
}
201+
} as const;
202+
203+
const schema = {
204+
$id: 'https://example.com/schemas/user.json',
205+
type: 'object',
206+
properties: {
207+
user: { $ref: 'definitions.json#/definitions/user' },
208+
},
209+
required: ['user'],
210+
additionalProperties: false,
211+
} as const;
212+
213+
const payload = {
214+
user: {
215+
name: 'Alice',
216+
age: 25,
217+
},
218+
};
219+
220+
const validatedData = validate({
221+
payload,
222+
schema,
223+
externalRefs: [definitionSchema],
224+
formats,
225+
});
226+
```
227+
228+
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).
18229

19230
## Contribute
20231

packages/validation/package.json

+35-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"name": "Amazon Web Services",
77
"url": "https://aws.amazon.com"
88
},
9-
"private": true,
109
"scripts": {
1110
"test": "vitest --run",
1211
"test:unit": "vitest --run",
@@ -18,7 +17,7 @@
1817
"test:e2e": "echo \"Not implemented\"",
1918
"build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json",
2019
"build:esm": "tsc --build tsconfig.esm.json && echo '{ \"type\": \"module\" }' > lib/esm/package.json",
21-
"build": "echo \"Not implemented\"",
20+
"build": "npm run build:esm & npm run build:cjs",
2221
"lint": "biome lint .",
2322
"lint:fix": "biome check --write .",
2423
"prepack": "node ../../.github/scripts/release_patch_package_json.js ."
@@ -29,12 +28,42 @@
2928
"exports": {
3029
".": {
3130
"require": {
32-
"types": "./lib/cjs/index.d.ts",
33-
"default": "./lib/cjs/index.js"
31+
"types": "./lib/cjs/validate.d.ts",
32+
"default": "./lib/cjs/validate.js"
3433
},
3534
"import": {
36-
"types": "./lib/esm/index.d.ts",
37-
"default": "./lib/esm/index.js"
35+
"types": "./lib/esm/validate.d.ts",
36+
"default": "./lib/esm/validate.js"
37+
}
38+
},
39+
"./middleware": {
40+
"require": {
41+
"types": "./lib/cjs/middleware.d.ts",
42+
"default": "./lib/cjs/middleware.js"
43+
},
44+
"import": {
45+
"types": "./lib/esm/middleware.d.ts",
46+
"default": "./lib/esm/middleware.js"
47+
}
48+
},
49+
"./errors": {
50+
"require": {
51+
"types": "./lib/cjs/errors.d.ts",
52+
"default": "./lib/cjs/errors.js"
53+
},
54+
"import": {
55+
"types": "./lib/esm/errors.d.ts",
56+
"default": "./lib/esm/errors.js"
57+
}
58+
},
59+
"./decorator": {
60+
"require": {
61+
"types": "./lib/cjs/decorator.d.ts",
62+
"default": "./lib/cjs/decorator.js"
63+
},
64+
"import": {
65+
"types": "./lib/esm/decorator.d.ts",
66+
"default": "./lib/esm/decorator.js"
3867
}
3968
}
4069
},

0 commit comments

Comments
 (0)