Skip to content

Commit c72a4f7

Browse files
committed
feat: add envelopes & entrypoint
1 parent 7c6eba6 commit c72a4f7

File tree

3 files changed

+165
-1
lines changed

3 files changed

+165
-1
lines changed

Diff for: packages/jmespath/src/envelopes.ts

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { search } from './search.js';
2+
import { PowertoolsFunctions } from './PowertoolsFunctions.js';
3+
import type { ParsingOptions, JSONObject } from './types.js';
4+
5+
/**
6+
* Searches and extracts data using JMESPath
7+
*
8+
* Envelope being the JMESPath expression to extract the data you're after
9+
*
10+
* Built-in JMESPath functions include: `powertools_json`, `powertools_base64`, `powertools_base64_gzip`
11+
*
12+
* @example
13+
* ```typescript
14+
* import { extractDataFromEnvelope } from '@aws-lambda-powertools/jmespath/envelopes';
15+
*
16+
* type CustomEvent = {
17+
* body: string; // "{\"customerId\":\"dd4649e6-2484-4993-acb8-0f9123103394\"}"
18+
* };
19+
*
20+
* type EventBody = {
21+
* customerId: string;
22+
* };
23+
*
24+
* export const handler = async (event: CustomEvent): Promise<unknown> => {
25+
* const payload = extractDataFromEnvelope<EventBody>(event, "powertools_json(body)");
26+
* const { customerId } = payload; // now deserialized
27+
* // ...
28+
* };
29+
* ```
30+
*
31+
* We provide built-in envelopes for popular AWS Lambda event sources to easily decode and/or deserialize JSON objects.
32+
*
33+
* @example
34+
* ```typescript
35+
* import {
36+
* extractDataFromEnvelope,
37+
* SQS,
38+
* } from '@aws-lambda-powertools/jmespath/envelopes';
39+
* import type { SQSEvent } from 'aws-lambda';
40+
*
41+
* type MessageBody = {
42+
* customerId: string;
43+
* };
44+
*
45+
* export const handler = async (event: SQSEvent): Promise<unknown> => {
46+
* const records = extractDataFromEnvelope<Array<MessageBody>>(event, SQS);
47+
* for (const record in records) { // records is now a list containing the deserialized body of each message
48+
* const { customerId } = record;
49+
* }
50+
* };
51+
* ```
52+
*
53+
* @param data The JSON object to search
54+
* @param envelope The JMESPath expression to use
55+
* @param options The parsing options to use
56+
*/
57+
const extractDataFromEnvelope = <T>(
58+
data: JSONObject,
59+
envelope: string,
60+
options?: ParsingOptions
61+
): T => {
62+
if (!options) {
63+
options = { customFunctions: new PowertoolsFunctions() };
64+
}
65+
66+
return search(envelope, data, options) as T;
67+
};
68+
69+
const API_GATEWAY_REST = 'powertools_json(body)';
70+
const API_GATEWAY_HTTP = 'powertools_json(body)';
71+
const SQS = 'Records[*].powertools_json(body)';
72+
const SNS = 'Records[0].Sns.Message | powertools_json(@)';
73+
const EVENTBRIDGE = 'detail';
74+
const CLOUDWATCH_EVENTS_SCHEDULED = 'detail';
75+
const KINESIS_DATA_STREAM =
76+
'Records[*].kinesis.powertools_json(powertools_base64(data))';
77+
const CLOUDWATCH_LOGS =
78+
'awslogs.powertools_base64_gzip(data) | powertools_json(@).logEvents[*]';
79+
const S3_SNS_SQS =
80+
'Records[*].powertools_json(body).powertools_json(Message).Records[0]';
81+
const S3_SQS = 'Records[*].powertools_json(body).Records[0]';
82+
const S3_SNS_KINESIS_FIREHOSE =
83+
'records[*].powertools_json(powertools_base64(data)).powertools_json(Message).Records[0]';
84+
const S3_KINESIS_FIREHOSE =
85+
'records[*].powertools_json(powertools_base64(data)).Records[0]';
86+
const S3_EVENTBRIDGE_SQS = 'Records[*].powertools_json(body).detail';
87+
88+
export {
89+
extractDataFromEnvelope,
90+
API_GATEWAY_REST,
91+
API_GATEWAY_HTTP,
92+
SQS,
93+
SNS,
94+
EVENTBRIDGE,
95+
CLOUDWATCH_EVENTS_SCHEDULED,
96+
KINESIS_DATA_STREAM,
97+
CLOUDWATCH_LOGS,
98+
S3_SNS_SQS,
99+
S3_SQS,
100+
S3_SNS_KINESIS_FIREHOSE,
101+
S3_KINESIS_FIREHOSE,
102+
S3_EVENTBRIDGE_SQS,
103+
};

Diff for: packages/jmespath/src/search.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Parser } from './Parser.js';
2+
import type { ParsingOptions, JSONObject } from './types.js';
3+
4+
const parser = new Parser();
5+
6+
/**
7+
* Search for data in a JSON object using a JMESPath expression.
8+
*
9+
* @example
10+
* ```typescript
11+
* import { search } from '@aws-lambda-powertools/jmespath';
12+
*
13+
* const data = {
14+
* foo: {
15+
* bar: {
16+
* baz: 1
17+
* }
18+
* }
19+
* };
20+
*
21+
* const result = search('foo.bar.baz', data);
22+
* console.log(result); // 1
23+
* ```
24+
*
25+
* By default the search function will use all the built-in functions
26+
* present in the [JMESPath specification](https://jmespath.org/specification.html).
27+
*
28+
* Powertools for AWS Lambda provides some additional functions that can be used
29+
* by passing them in the `customFunctions` option.
30+
*
31+
* @example
32+
* ```typescript
33+
* import { search } from '@aws-lambda-powertools/jmespath';
34+
* import { PowertoolsFunctions } from '@aws-lambda-powertools/jmespath/functions';
35+
*
36+
* const data = {
37+
* body: "{\"foo\": \"bar\"}"
38+
* };
39+
*
40+
* const result = search(
41+
* 'powertools_json(body)',
42+
* data,
43+
* { customFunctions: new PowertoolsFunctions() }
44+
* );
45+
* console.log(result); // { foo: 'bar' }
46+
* ```
47+
*
48+
* @param expression The JMESPath expression to use
49+
* @param data The JSON object to search
50+
* @param options The parsing options to use
51+
*/
52+
const search = (
53+
expression: string,
54+
data: JSONObject,
55+
options?: ParsingOptions
56+
): unknown => {
57+
return parser.parse(expression).search(data, options);
58+
};
59+
60+
export { search };

Diff for: packages/jmespath/typedoc.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"../../typedoc.base.json"
44
],
55
"entryPoints": [
6-
"./src/index.ts",
6+
"./src/search.ts",
7+
"./src/errors.ts",
78
"./src/types.ts",
89
"./src/envelopes.ts",
910
"./src/Functions.ts",

0 commit comments

Comments
 (0)