Skip to content
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

docs(parser): add utility readme #2360

Merged
merged 68 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
266651b
init parser package
Sep 13, 2023
e94d6c8
add init config
Sep 13, 2023
ebf75c6
Merge branch 'main' into feat/parser
am29d Sep 20, 2023
4533572
Merge branch 'main' into feat/parser
am29d Sep 29, 2023
8bcd2fc
feat(logger): Support for external observability providers (#1511)
erikayao93 Jun 30, 2023
a25b7e0
chore(logger): PowertoolsLogFormatter docstring and variable naming u…
erikayao93 Jul 7, 2023
5c1234f
feat(logger): Support for external observability providers (#1511)
erikayao93 Jun 30, 2023
241e967
chore(logger): PowertoolsLogFormatter docstring and variable naming u…
erikayao93 Jul 7, 2023
f113ef1
chore(maintenance): bump dependencies & drop nodejs14x (#1687)
dreamorosi Sep 16, 2023
68d6500
chore: update release script to mark all utilities as alpha
dreamorosi Sep 18, 2023
94c55b0
chore: restore version to ease conflicts
dreamorosi Sep 27, 2023
0d96e66
chore: release version change
dreamorosi Sep 27, 2023
701e877
chore: release version change
dreamorosi Sep 27, 2023
50aa3e7
chore(maintenance): remove `createLogger` and `createTracer` helpers …
dreamorosi Oct 2, 2023
0bc7960
feat(logger): add esmodule support (#1734)
antstanley Oct 11, 2023
c7a8511
feat(commons): add esmodule support (#1735)
dreamorosi Oct 11, 2023
d9a62ea
feat(parameters): add esmodule support (#1736)
dreamorosi Oct 12, 2023
aec327b
feat(batch): add esmodule support (#1737)
dreamorosi Oct 12, 2023
90a7523
feat(internal): add esmodule support (#1738)
dreamorosi Oct 12, 2023
e5e42d0
feat(metrics): add esmodule support (#1739)
dreamorosi Oct 12, 2023
0de2ffd
feat(tracer): add esmodule support (#1741)
dreamorosi Oct 12, 2023
79c43c8
feat(idempotency): add esmodule support (#1743)
dreamorosi Oct 12, 2023
db08c22
chore(metrics): fix import
dreamorosi Oct 14, 2023
0ac3500
chore(ci): v2 release line
dreamorosi Oct 14, 2023
d1a3137
chore(ci): fix alpha versioning pre-release
dreamorosi Oct 15, 2023
d20269d
docs(maintenance): add processes tab (#1747)
dreamorosi Oct 18, 2023
9e7458d
chore(tracer): update warning to better format segment name (#1750)
dreamorosi Oct 18, 2023
09ca462
chore(internal): remove outdated notice files (#1752)
dreamorosi Oct 18, 2023
e7eca23
chore(maintenance): set `removeComments` to` false` in `tsconfig.json…
dreamorosi Oct 18, 2023
24c0a18
chore(docs): add invisible unicode char to decorator docs (#1755)
dreamorosi Oct 18, 2023
0b32e11
chore: remove extra comma
dreamorosi Oct 18, 2023
cf29d0a
chore(docs): upgrade doc intro
dreamorosi Oct 19, 2023
f04fee6
chore(ci): add workflow to publish v2 docs on merge (#1756)
dreamorosi Oct 19, 2023
9b06afe
chore(docs): upgrade doc intro
dreamorosi Oct 19, 2023
a68a720
chore(ci): remove mike commands
dreamorosi Oct 19, 2023
66bf1bc
chore(ci): upgrade mkdocs
dreamorosi Oct 19, 2023
f89c795
feat(logger): align sampling debug logs feature implementation with t…
shdq Oct 19, 2023
13b1d13
chore(logger): refactor types and interfaces (#1758)
dreamorosi Oct 20, 2023
cc171a7
chore(maintenance): bump Middy v4 & run tests (#1760)
dreamorosi Oct 20, 2023
52cc3bc
chore(parameters): fix esm bundling
dreamorosi Oct 21, 2023
740c601
chore(parameters): refactor provider constructor to init client as ne…
dreamorosi Oct 20, 2023
44da5be
chore(parameters): change declare client param
dreamorosi Oct 21, 2023
4aeecae
chore(commons): update Powertools UA middleware detection (#1762)
dreamorosi Oct 21, 2023
a5f8911
chore(layers) widen version check in e2e
dreamorosi Oct 21, 2023
490b2d0
chore(maintenance): enable `isolatedModules` and isolate cache (#1765)
dreamorosi Oct 23, 2023
ac7b5e8
Merge branch 'feat/v2' of github.com:aws-powertools/powertools-lambda…
dreamorosi Oct 23, 2023
a669cb3
fix: idempotency types
dreamorosi Oct 30, 2023
4f2ddae
chore(idempotency): refactor aws sdk init logic (#1768)
dreamorosi Oct 30, 2023
ae4c9ed
build(tracer): bump aws-xray-sdk-core to latest
dreamorosi Oct 30, 2023
38edc36
build(maintenance): bump aws sdk dev dependencies
dreamorosi Oct 31, 2023
2b3317f
Merge branch 'main' into feat/parser
am29d Oct 31, 2023
3a072aa
chore(logger): set default UTC timezone (#1775)
dreamorosi Nov 3, 2023
f54e1b5
merged update from v2
am29d Nov 10, 2023
20cde95
feat(parser): add built-in schemas (#1788)
am29d Nov 20, 2023
ce9f8a1
feat(parser): add schema envelopes (#1815)
am29d Dec 19, 2023
803f8d9
feat(parser): implement middy parser middleware (#1823)
am29d Dec 20, 2023
5343894
feat(parser): implement parser decorator (#1831)
am29d Dec 21, 2023
d81445d
feat(parser): add types for built-in schemas (#1838)
am29d Mar 6, 2024
a9f5d79
Merge branch 'main' into feat/parser
am29d Mar 7, 2024
b348b95
chore(parser): add parser subpath exports to package.json (#2179)
am29d Mar 11, 2024
0012f92
feat(parser): implement `safeParse` option (#2244)
am29d Mar 21, 2024
d751cb3
Merge branch 'main' into feat/parser
am29d Apr 2, 2024
badfef5
refresh package lock after merge
am29d Apr 2, 2024
e0de20b
docs(parser): add docs for parser utility (#1835)
am29d Apr 5, 2024
221c769
feat(parser): add custom parse error (#2339)
am29d Apr 9, 2024
8c2b5bf
Merge branch 'main' into feat/parser
dreamorosi Apr 15, 2024
080ae52
chore: remove rebase leftovers
dreamorosi Apr 15, 2024
e0d0529
docs(parser): add utility readme
dreamorosi Apr 15, 2024
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
2 changes: 1 addition & 1 deletion .github/scripts/release_patch_package_json.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ const betaPackages = [];
} catch (err) {
throw err;
}
})();
})();
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ tmp

# TS build files
tsconfig.tsbuildinfo
.tsbuildinfo
.tsbuildinfo
3 changes: 2 additions & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ npm t \
-w packages/metrics \
-w packages/tracer \
-w packages/idempotency \
-w packages/parameters
-w packages/parameters \
-w packages/parser
3 changes: 1 addition & 2 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
src
tests
jest.config.js
tsconfig.json
.vscode
.github
Expand All @@ -13,7 +12,7 @@ coverage
tslint.json
tsconfig.json
MakeFile
jest.config.js
jest.config.cjs
.npmignore
.eslintignore
.huskyrc.js
Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ You can use Powertools for AWS Lambda (TypeScript) by installing it with your fa
| **[Parameters (AppConfig)](./utilities/parameters.md#install)** | **`npm i @aws-lambda-powertools/parameters @aws-sdk/client-appconfigdata`**{.copyMe}:clipboard: | |
| **[Parser](./utilities/parser.md#install)** | **`npm i @aws-lambda-powertools/parser zod@~3`**{.copyMe}:clipboard: | |


=== "Lambda Layer"

You can add our layer both in the [AWS Lambda Console _(under `Layers`)_](https://eu-west-1.console.aws.amazon.com/lambda/home#/add/layer){target="_blank"}, or via your favorite infrastructure as code framework with the ARN value.
Expand Down Expand Up @@ -325,11 +324,12 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al
| [Parameters](./utilities/parameters.md) | High-level functions to retrieve one or more parameters from AWS SSM Parameter Store, AWS Secrets Manager, AWS AppConfig, and Amazon DynamoDB |
| [Idempotency](./utilities/idempotency.md) | Class method decorator, Middy middleware, and function wrapper to make your Lambda functions idempotent and prevent duplicate execution based on payload content. |
| [Batch Processing](./utilities/batch.md) | Utility to handle partial failures when processing batches from Amazon SQS, Amazon Kinesis Data Streams, and Amazon DynamoDB Streams. |
| [Parser](./utilities/parser.md) | Utility to parse and validate AWS Lambda event payloads using Zod, a TypeScript-first schema declaration and validation library. |

## Environment variables

???+ info
Explicit parameters take precedence over environment variables
Explicit parameters take precedence over environment variables

| Environment variable | Description | Utility | Default |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ------------------- |
Expand Down Expand Up @@ -438,4 +438,4 @@ These are our core principles to guide our decision making.
- __Keep it lean__. Additional dependencies are carefully considered for security and ease of maintenance, and prevent negatively impacting startup time.
- __We strive for backwards compatibility__. New features and changes should keep backwards compatibility. If a breaking change cannot be avoided, the deprecation and migration process should be clearly defined.
- __We work backwards from the community__. We aim to strike a balance of what would work best for 80% of customers. Emerging practices are considered and discussed via Requests for Comment (RFCs)
- __Progressive__. Utilities are designed to be incrementally adoptable for customers at any stage of their Serverless journey. They follow language idioms and their community’s common practices.
- __Progressive__. Utilities are designed to be incrementally adoptable for customers at any stage of their Serverless journey. They follow language idioms and their community’s common practices.
4 changes: 3 additions & 1 deletion docs/snippets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@
"@aws-sdk/client-secrets-manager": "^3.554.0",
"@aws-sdk/client-ssm": "^3.554.0",
"@aws-sdk/util-dynamodb": "^3.554.0",
"@middy/core": "^4.7.0",
"aws-sdk": "^2.1598.0",
"aws-sdk-client-mock": "^4.0.0",
"aws-sdk-client-mock-jest": "^4.0.0",
"axios": "^1.6.8",
"hashi-vault-js": "^0.4.14"
"hashi-vault-js": "^0.4.14",
"zod": "^3.22.4"
}
}
35 changes: 35 additions & 0 deletions docs/snippets/parser/decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Context } from 'aws-lambda';
import type { LambdaInterface } from '@aws-lambda-powertools/commons/types';
import { parser } from '@aws-lambda-powertools/parser';
import { z } from 'zod';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});

type Order = z.infer<typeof orderSchema>;

class Lambda implements LambdaInterface {
@parser({ schema: orderSchema })
public async handler(event: Order, _context: Context): Promise<void> {
// event is now typed as Order
for (const item of event.items) {
logger.info('Processing item', { item });
}
}
}

const myFunction = new Lambda();
export const handler = myFunction.handler.bind(myFunction);
36 changes: 36 additions & 0 deletions docs/snippets/parser/envelopeDecorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Context } from 'aws-lambda';
import type { LambdaInterface } from '@aws-lambda-powertools/commons/types';
import { parser } from '@aws-lambda-powertools/parser';
import { z } from 'zod';
import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});

type Order = z.infer<typeof orderSchema>;

class Lambda implements LambdaInterface {
@parser({ schema: orderSchema, envelope: EventBridgeEnvelope }) // (1)!
public async handler(event: Order, _context: Context): Promise<void> {
// event is now typed as Order
for (const item of event.items) {
logger.info('Processing item', item); // (2)!
}
}
}

const myFunction = new Lambda();
export const handler = myFunction.handler.bind(myFunction);
37 changes: 37 additions & 0 deletions docs/snippets/parser/envelopeMiddy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Context } from 'aws-lambda';
import { parser } from '@aws-lambda-powertools/parser/middleware';
import { z } from 'zod';
import middy from '@middy/core';
import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});

type Order = z.infer<typeof orderSchema>;

const lambdaHandler = async (
event: Order,
_context: Context
): Promise<void> => {
for (const item of event.items) {
// item is parsed as OrderItem
logger.info('Processing item', { item });
}
};

export const handler = middy(lambdaHandler).use(
parser({ schema: orderSchema, envelope: EventBridgeEnvelope })
);
21 changes: 21 additions & 0 deletions docs/snippets/parser/examplePayload.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": "0",
"id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718",
"detail-type": "OrderPurchased",
"source": "OrderService",
"account": "111122223333",
"time": "2020-10-22T18:43:48Z",
"region": "us-west-1",
"resources": ["some_additional"],
"detail": {
"id": 10876546789,
"description": "My order",
"items": [
{
"id": 1015938732,
"quantity": 1,
"description": "item xpto"
}
]
}
}
40 changes: 40 additions & 0 deletions docs/snippets/parser/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { Context } from 'aws-lambda';
import type { LambdaInterface } from '@aws-lambda-powertools/commons/types';
import { parser } from '@aws-lambda-powertools/parser';
import { z } from 'zod';
import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});

const orderEventSchema = EventBridgeSchema.extend({
detail: orderSchema, // (1)!
});

type OrderEvent = z.infer<typeof orderEventSchema>;

class Lambda implements LambdaInterface {
@parser({ schema: orderEventSchema }) // (2)!
public async handler(event: OrderEvent, _context: Context): Promise<void> {
for (const item of event.detail.items) {
// process OrderItem
logger.info('Processing item', { item }); // (3)!
}
}
}

const myFunction = new Lambda();
export const handler = myFunction.handler.bind(myFunction);
33 changes: 33 additions & 0 deletions docs/snippets/parser/manual.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { Context } from 'aws-lambda';
import { z } from 'zod';
import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas';
import type { EventBridgeEvent } from '@aws-lambda-powertools/parser/types';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});
type Order = z.infer<typeof orderSchema>;

export const handler = async (
event: EventBridgeEvent,
_context: Context
): Promise<void> => {
const parsedEvent = EventBridgeSchema.parse(event); // (1)!
logger.info('Parsed event', parsedEvent);

const orders: Order = EventBridgeEnvelope.parse(event, orderSchema); // (2)!
logger.info('Parsed orders', orders);
};
35 changes: 35 additions & 0 deletions docs/snippets/parser/manualSafeParse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Context } from 'aws-lambda';
import { z } from 'zod';
import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas';
import type { EventBridgeEvent } from '@aws-lambda-powertools/parser/types';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});

export const handler = async (
event: EventBridgeEvent,
_context: Context
): Promise<void> => {
const parsedEvent = EventBridgeSchema.safeParse(event); // (1)!
parsedEvent.success
? logger.info('Event parsed successfully', parsedEvent.data)
: logger.error('Event parsing failed', parsedEvent.error);
const parsedEvenlope = EventBridgeEnvelope.safeParse(event, orderSchema); // (2)!
parsedEvenlope.success
? logger.info('Event envelope parsed successfully', parsedEvenlope.data)
: logger.error('Event envelope parsing failed', parsedEvenlope.error);
};
36 changes: 36 additions & 0 deletions docs/snippets/parser/middy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Context } from 'aws-lambda';
import { parser } from '@aws-lambda-powertools/parser/middleware';
import { z } from 'zod';
import middy from '@middy/core';
import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

const orderSchema = z.object({
id: z.number().positive(),
description: z.string(),
items: z.array(
z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
})
),
optionalField: z.string().optional(),
});

type Order = z.infer<typeof orderSchema>;

const lambdaHandler = async (
event: Order,
_context: Context
): Promise<void> => {
for (const item of event.items) {
// item is parsed as OrderItem
logger.info('Processing item', { item });
}
};

export const handler = middy(lambdaHandler).use(
parser({ schema: orderSchema })
);
21 changes: 21 additions & 0 deletions docs/snippets/parser/refine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { z } from 'zod';

const orderItemSchema = z.object({
id: z.number().positive(),
quantity: z.number(),
description: z.string(),
});

export const orderSchema = z
.object({
id: z.number().positive(),
description: z.string(),
items: z.array(orderItemSchema).refine((items) => items.length > 0, {
message: 'Order must have at least one item', // (1)!
}),
optionalField: z.string().optional(),
})
.refine((order) => order.id > 100 && order.items.length > 100, {
message:
'All orders with more than 100 items must have an id greater than 100', // (2)!
});
Loading