Skip to content

Commit 4998d6b

Browse files
authored
feat(parser): make parse function available standalone (#4300)
1 parent b8ca368 commit 4998d6b

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

packages/parser/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { ParseError } from './errors.js';
2+
export { parse } from './parser.js';
23
export { parser } from './parserDecorator.js';
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { z } from 'zod';
3+
import { EventBridgeEnvelope } from '../../src/envelopes/eventbridge.js';
4+
import { SqsEnvelope } from '../../src/envelopes/sqs.js';
5+
import { ParseError } from '../../src/errors.js';
6+
import { parse } from '../../src/parser.js';
7+
import type { EventBridgeEvent, SqsEvent } from '../../src/types/index.js';
8+
import { getTestEvent } from './helpers/utils.js';
9+
10+
describe('Parser', () => {
11+
const schema = z
12+
.object({
13+
name: z.string(),
14+
age: z.number(),
15+
})
16+
.strict();
17+
const baseSqsEvent = getTestEvent<SqsEvent>({
18+
eventsPath: 'sqs',
19+
filename: 'base',
20+
});
21+
const baseEventBridgeEvent = getTestEvent<EventBridgeEvent>({
22+
eventsPath: 'eventbridge',
23+
filename: 'base',
24+
});
25+
const JSONPayload = { name: 'John', age: 18 };
26+
27+
it('parses an event with schema and envelope', async () => {
28+
// Prepare
29+
const event = structuredClone(baseSqsEvent);
30+
event.Records[1].body = 'bar';
31+
32+
// Act
33+
34+
const result = parse(event, SqsEnvelope, z.string());
35+
36+
// Assess
37+
expect(result).toStrictEqual(['Test message.', 'bar']);
38+
});
39+
40+
it('throws when envelope does not match', async () => {
41+
// Prepare
42+
const event = structuredClone(baseEventBridgeEvent);
43+
44+
// Act & Assess
45+
expect(() => parse(event, SqsEnvelope, z.string())).toThrow();
46+
});
47+
48+
it('throws when schema does not match', async () => {
49+
// Prepare
50+
const event = structuredClone(baseSqsEvent);
51+
// @ts-expect-error - setting an invalid body
52+
event.Records[1].body = undefined;
53+
54+
// Act & Assess
55+
expect(() => parse(event, SqsEnvelope, z.string())).toThrow();
56+
});
57+
58+
it('parses the event successfully', async () => {
59+
// Prepare
60+
const event = 42;
61+
62+
// Act
63+
const result = parse(event, undefined, z.number());
64+
65+
// Assess
66+
expect(result).toEqual(event);
67+
});
68+
69+
it('throws when the event does not match the schema', async () => {
70+
// Prepare
71+
const event = structuredClone(JSONPayload);
72+
73+
// Act & Assess
74+
expect(() => parse(event, undefined, z.number())).toThrow();
75+
});
76+
77+
it('returns the payload when using safeParse', async () => {
78+
// Prepare
79+
const event = structuredClone(JSONPayload);
80+
81+
// Act
82+
const result = parse(event, undefined, schema, true);
83+
84+
// Assess
85+
expect(result).toEqual({
86+
success: true,
87+
data: event,
88+
});
89+
});
90+
91+
it('returns the error when using safeParse and the payload is invalid', async () => {
92+
// Prepare
93+
const event = structuredClone(JSONPayload);
94+
95+
// Act
96+
const result = parse(event, undefined, z.string(), true);
97+
98+
// Assess
99+
expect(result).toEqual({
100+
success: false,
101+
error: expect.any(ParseError),
102+
originalEvent: event,
103+
});
104+
});
105+
106+
it('returns the payload when using safeParse with envelope', async () => {
107+
// Prepare
108+
const detail = structuredClone(JSONPayload);
109+
const event = structuredClone(baseEventBridgeEvent);
110+
event.detail = detail;
111+
112+
// Act
113+
const result = parse(event, EventBridgeEnvelope, schema, true);
114+
115+
// Assess
116+
expect(result).toStrictEqual({
117+
success: true,
118+
data: detail,
119+
});
120+
});
121+
122+
it('returns an error when using safeParse with envelope and the payload is invalid', async () => {
123+
// Prepare
124+
const event = structuredClone(baseEventBridgeEvent);
125+
126+
// Act
127+
const result = parse(event, EventBridgeEnvelope, z.string(), true);
128+
129+
// Assess
130+
expect(result).toStrictEqual({
131+
success: false,
132+
error: expect.any(ParseError),
133+
originalEvent: event,
134+
});
135+
});
136+
});

0 commit comments

Comments
 (0)