Skip to content

Commit 4f8b15a

Browse files
authored
docs(validation): add main docs page (#3717)
1 parent 16208c2 commit 4f8b15a

16 files changed

+410
-531
lines changed

Diff for: docs/utilities/validation.md

+51-531
Large diffs are not rendered by default.
File renamed without changes.
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Logger } from '@aws-lambda-powertools/logger';
2+
import { validate } from '@aws-lambda-powertools/validation';
3+
import { SchemaValidationError } from '@aws-lambda-powertools/validation/errors';
4+
import Ajv2019 from 'ajv/dist/2019';
5+
import { inboundSchema } from './schemas.js';
6+
7+
const logger = new Logger();
8+
9+
const ajv = new Ajv2019();
10+
11+
export const handler = async (event: unknown) => {
12+
try {
13+
await validate({
14+
payload: event,
15+
schema: inboundSchema,
16+
ajv, // (1)!
17+
});
18+
19+
return {
20+
message: 'ok',
21+
};
22+
} catch (error) {
23+
if (error instanceof SchemaValidationError) {
24+
logger.error('Schema validation failed', error);
25+
throw new Error('Invalid event payload');
26+
}
27+
28+
throw error;
29+
}
30+
};
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Logger } from '@aws-lambda-powertools/logger';
2+
import { validate } from '@aws-lambda-powertools/validation';
3+
import { SchemaValidationError } from '@aws-lambda-powertools/validation/errors';
4+
import schemaWithCustomFormat from './samples/schemaWithCustomFormat.json';
5+
6+
const logger = new Logger();
7+
8+
const customFormats = {
9+
awsaccountid: /^\d{12}$/,
10+
creditcard: (value: string) => {
11+
// Luhn algorithm (for demonstration purposes only - do not use in production)
12+
const sum = value
13+
.split('')
14+
.reverse()
15+
.reduce((acc, digit, index) => {
16+
const num = Number.parseInt(digit, 10);
17+
return acc + (index % 2 === 0 ? num : num < 5 ? num * 2 : num * 2 - 9);
18+
}, 0);
19+
20+
return sum % 10 === 0;
21+
},
22+
};
23+
24+
export const handler = async (event: unknown) => {
25+
try {
26+
await validate({
27+
payload: event,
28+
schema: schemaWithCustomFormat,
29+
formats: customFormats,
30+
});
31+
32+
return {
33+
message: 'ok',
34+
};
35+
} catch (error) {
36+
if (error instanceof SchemaValidationError) {
37+
logger.error('Schema validation failed', error);
38+
throw new Error('Invalid event payload');
39+
}
40+
41+
throw error;
42+
}
43+
};

Diff for: examples/snippets/validation/advancedExternalRefs.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { validator } from '@aws-lambda-powertools/validation/decorator';
2+
import type { Context } from 'aws-lambda';
3+
import {
4+
type InboundSchema,
5+
defsSchema,
6+
inboundSchema,
7+
outboundSchema,
8+
} from './schemasWithExternalRefs.js';
9+
10+
class Lambda {
11+
@validator({
12+
inboundSchema,
13+
outboundSchema,
14+
externalRefs: [defsSchema],
15+
})
16+
async handler(event: InboundSchema, _context: Context) {
17+
return {
18+
message: `processed ${event.userId}`,
19+
success: true,
20+
};
21+
}
22+
}
23+
24+
const lambda = new Lambda();
25+
export const handler = lambda.handler.bind(lambda);
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { validator } from '@aws-lambda-powertools/validation/decorator';
2+
import type { Context } from 'aws-lambda';
3+
import {
4+
type InboundSchema,
5+
type OutboundSchema,
6+
inboundSchema,
7+
outboundSchema,
8+
} from './schemas.js';
9+
10+
class Lambda {
11+
@validator({
12+
inboundSchema,
13+
outboundSchema,
14+
})
15+
async handler(
16+
event: InboundSchema,
17+
_context: Context
18+
): Promise<OutboundSchema> {
19+
return {
20+
statusCode: 200,
21+
body: `Hello from ${event.userId}`,
22+
};
23+
}
24+
}
25+
26+
const lambda = new Lambda();
27+
export const handler = lambda.handler.bind(lambda);
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { validator } from '@aws-lambda-powertools/validation/decorator';
2+
import type { Context } from 'aws-lambda';
3+
import { type InboundSchema, inboundSchema } from './schemas.js';
4+
5+
class Lambda {
6+
@validator({
7+
inboundSchema,
8+
envelope: 'detail',
9+
})
10+
async handler(event: InboundSchema, context: Context) {
11+
return {
12+
message: `processed ${event.userId}`,
13+
success: true,
14+
};
15+
}
16+
}
17+
18+
const lambda = new Lambda();
19+
export const handler = lambda.handler.bind(lambda);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { SQS } from '@aws-lambda-powertools/jmespath/envelopes';
2+
import { Logger } from '@aws-lambda-powertools/logger';
3+
import { validator } from '@aws-lambda-powertools/validation/middleware';
4+
import middy from '@middy/core';
5+
import { type InboundSchema, inboundSchema } from './schemas.js';
6+
7+
const logger = new Logger();
8+
9+
export const handler = middy()
10+
.use(
11+
validator({
12+
inboundSchema,
13+
envelope: SQS,
14+
})
15+
)
16+
.handler(async (event: Array<InboundSchema>) => {
17+
for (const record of event) {
18+
logger.info(`Processing message ${record.userId}`);
19+
}
20+
});

Diff for: examples/snippets/validation/gettingStartedMiddy.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { validator } from '@aws-lambda-powertools/validation/middleware';
2+
import middy from '@middy/core';
3+
import {
4+
type InboundSchema,
5+
type OutboundSchema,
6+
inboundSchema,
7+
outboundSchema,
8+
} from './schemas.js';
9+
10+
export const handler = middy()
11+
.use(
12+
validator({
13+
inboundSchema,
14+
outboundSchema,
15+
})
16+
)
17+
.handler(
18+
async (event: InboundSchema): Promise<OutboundSchema> => ({
19+
statusCode: 200,
20+
body: `Hello from ${event.userId}`,
21+
})
22+
);
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Logger } from '@aws-lambda-powertools/logger';
2+
import { validate } from '@aws-lambda-powertools/validation';
3+
import { SchemaValidationError } from '@aws-lambda-powertools/validation/errors';
4+
import { type InboundSchema, inboundSchema } from './schemas.js';
5+
6+
const logger = new Logger();
7+
8+
export const handler = async (event: InboundSchema) => {
9+
try {
10+
validate({
11+
payload: event,
12+
schema: inboundSchema,
13+
});
14+
15+
return {
16+
message: 'ok', // (1)!
17+
};
18+
} catch (error) {
19+
if (error instanceof SchemaValidationError) {
20+
logger.error('Schema validation failed', error);
21+
throw new Error('Invalid event payload');
22+
}
23+
24+
throw error;
25+
}
26+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "0",
3+
"id": "12345678-1234-1234-1234-123456789012",
4+
"detail-type": "myDetailType",
5+
"source": "myEventSource",
6+
"account": "123456789012",
7+
"time": "2017-12-22T18:43:48Z",
8+
"region": "us-west-2",
9+
"resources": [],
10+
"detail": {
11+
"userId": "123"
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Records": [
3+
{
4+
"messageId": "c80e8021-a70a-42c7-a470-796e1186f753",
5+
"receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
6+
"body": "{\"userId\":\"123\"}",
7+
"attributes": {
8+
"ApproximateReceiveCount": "3",
9+
"SentTimestamp": "1529104986221",
10+
"SenderId": "AIDAIC6K7FJUZ7Q",
11+
"ApproximateFirstReceiveTimestamp": "1529104986230"
12+
},
13+
"messageAttributes": {},
14+
"md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
15+
"eventSource": "aws:sqs",
16+
"eventSourceARN": "arn:aws:sqs:us-west-2:123456789012:my-queue",
17+
"awsRegion": "us-west-2"
18+
},
19+
{
20+
"messageId": "c80e8021-a70a-42c7-a470-796e1186f753",
21+
"receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
22+
"body": "{\"userId\":\"456\"}",
23+
"attributes": {
24+
"ApproximateReceiveCount": "3",
25+
"SentTimestamp": "1529104986221",
26+
"SenderId": "AIDAIC6K7FJUZ7Q",
27+
"ApproximateFirstReceiveTimestamp": "1529104986230"
28+
},
29+
"messageAttributes": {},
30+
"md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
31+
"eventSource": "aws:sqs",
32+
"eventSourceARN": "arn:aws:sqs:us-west-2:123456789012:my-queue",
33+
"awsRegion": "us-west-2"
34+
}
35+
]
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"accountId": {
5+
"type": "string",
6+
"format": "awsaccountid"
7+
},
8+
"creditCard": {
9+
"type": "string",
10+
"format": "creditcard"
11+
}
12+
},
13+
"required": [
14+
"accountId"
15+
]
16+
}

Diff for: examples/snippets/validation/schemas.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const inboundSchema = {
2+
type: 'object',
3+
properties: {
4+
userId: {
5+
type: 'string',
6+
},
7+
},
8+
required: ['userId'],
9+
} as const;
10+
11+
type InboundSchema = {
12+
userId: string;
13+
};
14+
15+
const outboundSchema = {
16+
type: 'object',
17+
properties: {
18+
body: {
19+
type: 'string',
20+
},
21+
statusCode: {
22+
type: 'number',
23+
},
24+
},
25+
required: ['body', 'statusCode'],
26+
} as const;
27+
28+
type OutboundSchema = {
29+
body: string;
30+
statusCode: number;
31+
};
32+
33+
export {
34+
inboundSchema,
35+
outboundSchema,
36+
type InboundSchema,
37+
type OutboundSchema,
38+
};
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const defsSchema = {
2+
$id: 'http://example.com/schemas/defs.json',
3+
definitions: {
4+
int: { type: 'integer' },
5+
str: { type: 'string' },
6+
},
7+
} as const;
8+
9+
const inboundSchema = {
10+
$id: 'http://example.com/schemas/inbound.json',
11+
type: 'object',
12+
properties: {
13+
userId: { $ref: 'defs.json#/definitions/str' },
14+
},
15+
required: ['userId'],
16+
} as const;
17+
18+
type InboundSchema = {
19+
userId: string;
20+
};
21+
22+
const outboundSchema = {
23+
$id: 'http://example.com/schemas/outbound.json',
24+
type: 'object',
25+
properties: {
26+
body: { $ref: 'defs.json#/definitions/str' },
27+
statusCode: { $ref: 'defs.json#/definitions/int' },
28+
},
29+
required: ['body', 'statusCode'],
30+
} as const;
31+
32+
type OutboundSchema = {
33+
body: string;
34+
statusCode: number;
35+
};
36+
37+
export {
38+
defsSchema,
39+
inboundSchema,
40+
outboundSchema,
41+
type InboundSchema,
42+
type OutboundSchema,
43+
};

Diff for: mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ nav:
4646
- utilities/batch.md
4747
- utilities/jmespath.md
4848
- utilities/parser.md
49+
- utilities/validation.md
4950
- API reference: api"
5051
- Processes:
5152
- Roadmap: roadmap.md

0 commit comments

Comments
 (0)