@cazoo/events
v5.0.4
Published
Raise Cazoo business events
Downloads
137
Readme
@cazoo/events
Used for raising and parsing Cazoo business events. Abstracts away EventBridge, which we are using as an event bus.
Basic Usage
EventClient.publish
Validates and publish an event. It will fail with a validation exception if the event is not valid.
import { EventClient, DoNotValidator, parse } from '@cazoo/events';
export const someHandler = async (ev, context) => {
const { name, payload } = parse(ev);
const registryARN = proces.env.SCHEMA_REGISTRY_ARN;
/* Implement your Lambda logic here */
// Raise a new event on the shared EventBridge event bus.
const validator = new DynamicSchemaValidator(registryARN);
const client = new EventClient({ context, validator });
const event = {
name: "orderPlaced",
payload: { foo: 'bar' }
};
await client.publish(event)
}
Targeting a custom event bus
It's possible to use an Environment Variable CAZOO_EVENTS_TARGET_EVENT_BUS
to use a custom event bus, you can also manually use a
custom event bus using the information below.
If eventBusName
parameter is not provided, the default event bus is targeted, instead.
const client = new EventClient({
context: myContext,
eventBusName: "custom-event-bus"
});
Validating target event bus
If you wish to provide a custom event bus as your target, you can also optionally validate the existence of the event bus by using the eventBusValidation
boolean as shown below:
const client = new EventClient({
context: myContext,
eventBusName: "custom-event-bus",
eventBusValidation: true
})
IAM Permissions
If you want to use event bus validation, then you will need the events:DescribeEventBus
IAM permission on your Lambda.
Note: If eventBusValidation
is set, then the eventBusName
parameter or the environment variable CAZOO_EVENTS_TARGET_EVENT_BUS
must be provided, else an error will throw
Configuring the event bridge client
You can provide your own config for the event bridge client the library uses.
const client = new EventClient({
context: myContext,
clientConfig: { endpoint: 'http://localhost:3213' }
});
Runtime validation
We now have support for runtime validation of events via the EventClient
class. This class will dynamically fetch schemas from the Eventbridge Schema Registry and validate messages before they are raised.
// We use the ARN of the schema registry to look up event schemas
const registryArn = process.env.CAZOO_EVENT_REGISTRY_ARN ||
"arn:aws:schemas:eu-west-1:571578941547:registry/cazoo-events"
const validator = new DynamicSchemaValidator(registryArn)
// We create a client passing a validator and the lambda context
const client = new EventClient({
context,
validator,
});
try {
const result = await client.publish({
name: "deliveryCancelled",
payload: {
orderNumber: "abc-123"
}
});
} catch (e) {
console.log(e.message);
console.log(JSON.stringify(e.errors, null, 2))
}
/* Yields the following error
data must NOT have additional properties, data must have required property 'order_number'
[
{
"keyword": "additionalProperties",
"instancePath": "",
"schemaPath": "#/additionalProperties",
"params": {
"additionalProperty": "orderNumber"
},
"message": "must NOT have additional properties"
},
{
"keyword": "required",
"dataPath": "",
"instancePath": "#/required",
"params": {
"missingProperty": "order_number"
},
"message": "must have required property 'order_number'"
}
]
*/
NOT RECOMMENDED
You can also explicitly disable validation with the DoNotValidator
.
const validator = new DoNotValidator()
const client = new EventClient({ context, validator });
// This won't throw
const result = await client.publish({
name: "anyOldRubbish",
payload: {
foo: "bar"
}
});
XRAY
If you'd like to enable xray tracing you can just pass it as part of the eventClient configuration:
const client = new EventClient({ context, validator, config: { xrayEnabled: true } });
Also add the xray dependency to your package.json aws-xray-sdk@3
and make sure you add the required permission to your lambda from the latest AWS documentation https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html.
IAM Permissions
Your lambda will require the following IAM permissions to validate schemas.
Serverless
iamRoleStatements:
- Effect: Allow
Action:
- schemas:DescribeSchema
Resource:
- arn:aws:schemas:${AWS::Region}:${AWS::AccountId}:schema/REGISTRY_NAME/SCHEMA_NAME
- ...
Terraform
variable "account_id" {}
variable "region" {}
variable "registry_name" {}
variable "schema_name {}
data "aws_iam_policy_document" "allow_describe_schema" {
statement {
sid = "AllowDescribeSchema"
actions = [
"schemas:DescribeSchema"
]
resources = [
"arn:aws:schemas:${var.region}:${var.account_id}:schema/${var.registry_name}/${var.schema_name}",
...
]
}
}
resource "aws_iam_policy" "allow_describe_schema" {
name = "allow-describe-schema"
path = "/"
policy = data.aws_iam_policy_document.allow_describe_schema.json
}
# attach the policy to your lambda role.
resource "aws_iam_role_policy_attachment" "attach_allow_describe_schema" {
role = aws_iam_role.lambda_execution_role.name
policy_arn = aws_iam_policy.allow_describe_schema.arn
}