@vyriy/handler 0.5.6 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -2
- package/api.js +10 -10
- package/dynamodb.d.ts +2 -0
- package/dynamodb.js +7 -0
- package/eventBridge.d.ts +2 -0
- package/eventBridge.js +7 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/package.json +47 -7
- package/s3.d.ts +2 -0
- package/s3.js +7 -0
- package/ses.d.ts +2 -0
- package/ses.js +7 -0
- package/wrapper/headers.js +4 -3
- package/wrapper/stream.js +5 -2
package/README.md
CHANGED
|
@@ -122,6 +122,42 @@ export const handler = sns(async (event) => {
|
|
|
122
122
|
});
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
+
Use a prebuilt DynamoDB Streams handler chain:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { dynamodb } from '@vyriy/handler';
|
|
129
|
+
|
|
130
|
+
export const handler = dynamodb(async (event) => {
|
|
131
|
+
for (const record of event.Records) {
|
|
132
|
+
console.info(record.eventName);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use a prebuilt S3 event handler chain:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { s3 } from '@vyriy/handler';
|
|
141
|
+
|
|
142
|
+
export const handler = s3(async (event) => {
|
|
143
|
+
for (const record of event.Records) {
|
|
144
|
+
console.info(record.s3.bucket.name, record.s3.object.key);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Use a prebuilt SES receipt handler chain:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { ses } from '@vyriy/handler';
|
|
153
|
+
|
|
154
|
+
export const handler = ses(async (event) => {
|
|
155
|
+
for (const record of event.Records) {
|
|
156
|
+
console.info(record.ses.mail.messageId, record.ses.mail.source);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
125
161
|
Use a prebuilt schedule handler chain:
|
|
126
162
|
|
|
127
163
|
```ts
|
|
@@ -132,6 +168,16 @@ export const handler = schedule(async (event) => {
|
|
|
132
168
|
});
|
|
133
169
|
```
|
|
134
170
|
|
|
171
|
+
Use a prebuilt EventBridge custom event handler chain:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { eventBridge } from '@vyriy/handler';
|
|
175
|
+
|
|
176
|
+
export const handler = eventBridge(async (event) => {
|
|
177
|
+
console.info('EventBridge event:', event.source, event['detail-type'], event.detail);
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
135
181
|
Compose a custom handler pipeline from individual helpers:
|
|
136
182
|
|
|
137
183
|
```ts
|
|
@@ -193,6 +239,18 @@ export const handler = compose(
|
|
|
193
239
|
- `streamApi`
|
|
194
240
|
Response streaming API Gateway chain with the same wrapper behavior as `api`. Handlers receive `(event, responseStream, context)` and write directly to the Lambda response stream.
|
|
195
241
|
|
|
242
|
+
- `dynamodb`
|
|
243
|
+
DynamoDB Streams chain with logging, timeout handling, context setup, smoke checks, and rethrown errors.
|
|
244
|
+
|
|
245
|
+
- `eventBridge`
|
|
246
|
+
EventBridge custom event chain with logging, timeout handling, context setup, smoke checks, and rethrown errors.
|
|
247
|
+
|
|
248
|
+
- `s3`
|
|
249
|
+
S3 event chain with logging, timeout handling, context setup, smoke checks, and rethrown errors.
|
|
250
|
+
|
|
251
|
+
- `ses`
|
|
252
|
+
SES receipt rule chain for incoming email processing with logging, timeout handling, context setup, smoke checks, and rethrown errors.
|
|
253
|
+
|
|
196
254
|
- `schedule`
|
|
197
255
|
EventBridge schedule chain with logging, timeout handling, context setup, smoke checks, and rethrown errors.
|
|
198
256
|
|
|
@@ -364,7 +422,7 @@ export const handler = withSmoke()(async () => {
|
|
|
364
422
|
});
|
|
365
423
|
```
|
|
366
424
|
|
|
367
|
-
`withSmoke()` is used by the API, schedule, SNS, and SQS chains.
|
|
425
|
+
`withSmoke()` is used by the API, DynamoDB Streams, S3, SES receipt, schedule, SNS, and SQS chains.
|
|
368
426
|
|
|
369
427
|
## Types
|
|
370
428
|
|
|
@@ -377,5 +435,6 @@ import type { Context, Decorator, Handler, HandlerParams, Response } from '@vyri
|
|
|
377
435
|
## Notes
|
|
378
436
|
|
|
379
437
|
- `api` includes API-specific wrappers such as healthcheck handling, default headers, and CORS preflight handling
|
|
380
|
-
- `schedule`, `sns`, and `sqs` use `withError()` so failures are rethrown for event-source retry behavior
|
|
438
|
+
- `dynamodb`, `s3`, `ses`, `schedule`, `sns`, and `sqs` use `withError()` so failures are rethrown for event-source retry behavior
|
|
439
|
+
- `ses` targets SES receipt rule Lambda events for incoming email; SES event publishing notifications can still be handled through the `sns` chain when delivered via SNS
|
|
381
440
|
- `withSmoke()` delegates matching to `@vyriy/smoke` and returns its API Gateway-compatible response
|
package/api.js
CHANGED
|
@@ -9,16 +9,16 @@ import { streamWithHeaders, withHeaders } from './wrapper/headers.js';
|
|
|
9
9
|
import { streamWithCors, withCors } from './wrapper/cors.js';
|
|
10
10
|
import { streamWithChaos, withChaos } from './wrapper/chaos.js';
|
|
11
11
|
export const api = compose(withApiError(), withLogger(), withTimeout(), withContext(), withSmoke(), withHealthcheck(), withHeaders({
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
12
|
+
'access-control-allow-origin': '*',
|
|
13
|
+
'access-control-allow-methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
|
|
14
|
+
'access-control-allow-headers': 'Content-Type, Authorization, X-Requested-With, X-Api-Key, Accept, User-Agent, X-CSRF-Token',
|
|
15
|
+
'content-type': 'application/json',
|
|
16
|
+
'x-robots-tag': 'noindex, nofollow',
|
|
17
17
|
}), withCors(), withChaos());
|
|
18
18
|
export const streamApi = streamCompose(streamWithApiError(), streamWithLogger(), streamWithTimeout(), streamWithContext(), streamWithSmoke(), streamWithHealthcheck(), streamWithHeaders({
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
19
|
+
'access-control-allow-origin': '*',
|
|
20
|
+
'access-control-allow-methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
|
|
21
|
+
'access-control-allow-headers': 'Content-Type, Authorization, X-Requested-With, X-Api-Key, Accept, User-Agent, X-CSRF-Token',
|
|
22
|
+
'content-type': 'application/json',
|
|
23
|
+
'x-robots-tag': 'noindex, nofollow',
|
|
24
24
|
}), streamWithCors(), streamWithChaos());
|
package/dynamodb.d.ts
ADDED
package/dynamodb.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { compose } from './compose.js';
|
|
2
|
+
import { withError } from './wrapper/error.js';
|
|
3
|
+
import { withLogger } from './wrapper/logger.js';
|
|
4
|
+
import { withTimeout } from './wrapper/timeout.js';
|
|
5
|
+
import { withContext } from './wrapper/context.js';
|
|
6
|
+
import { withSmoke } from './wrapper/smoke.js';
|
|
7
|
+
export const dynamodb = compose(withError(), withLogger(), withTimeout(), withContext(), withSmoke());
|
package/eventBridge.d.ts
ADDED
package/eventBridge.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { compose } from './compose.js';
|
|
2
|
+
import { withError } from './wrapper/error.js';
|
|
3
|
+
import { withLogger } from './wrapper/logger.js';
|
|
4
|
+
import { withTimeout } from './wrapper/timeout.js';
|
|
5
|
+
import { withContext } from './wrapper/context.js';
|
|
6
|
+
import { withSmoke } from './wrapper/smoke.js';
|
|
7
|
+
export const eventBridge = compose(withError(), withLogger(), withTimeout(), withContext(), withSmoke());
|
package/index.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export * from './api.js';
|
|
2
2
|
export * from './compose.js';
|
|
3
|
+
export * from './dynamodb.js';
|
|
4
|
+
export * from './eventBridge.js';
|
|
3
5
|
export * from './factory.js';
|
|
6
|
+
export * from './s3.js';
|
|
4
7
|
export * from './schedule.js';
|
|
8
|
+
export * from './ses.js';
|
|
5
9
|
export * from './sns.js';
|
|
6
10
|
export * from './sqs.js';
|
|
7
11
|
export * from './wrapper/context.js';
|
package/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export * from './api.js';
|
|
2
2
|
export * from './compose.js';
|
|
3
|
+
export * from './dynamodb.js';
|
|
4
|
+
export * from './eventBridge.js';
|
|
3
5
|
export * from './factory.js';
|
|
6
|
+
export * from './s3.js';
|
|
4
7
|
export * from './schedule.js';
|
|
8
|
+
export * from './ses.js';
|
|
5
9
|
export * from './sns.js';
|
|
6
10
|
export * from './sqs.js';
|
|
7
11
|
export * from './wrapper/context.js';
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vyriy/handler",
|
|
3
|
-
"version": "0.5
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "Composable AWS Lambda handler chains and wrappers for Vyriy projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@types/aws-lambda": "^8.10.
|
|
8
|
-
"@vyriy/chaos": "0.5
|
|
9
|
-
"@vyriy/config": "0.5
|
|
10
|
-
"@vyriy/logger": "0.5
|
|
11
|
-
"@vyriy/smoke": "0.5
|
|
12
|
-
"@vyriy/timeout": "0.5
|
|
7
|
+
"@types/aws-lambda": "^8.10.162",
|
|
8
|
+
"@vyriy/chaos": "0.6.5",
|
|
9
|
+
"@vyriy/config": "0.6.5",
|
|
10
|
+
"@vyriy/logger": "0.6.5",
|
|
11
|
+
"@vyriy/smoke": "0.6.5",
|
|
12
|
+
"@vyriy/timeout": "0.6.5"
|
|
13
13
|
},
|
|
14
14
|
"agents": "./AGENTS.md",
|
|
15
15
|
"license": "MIT",
|
|
@@ -46,6 +46,26 @@
|
|
|
46
46
|
"import": "./compose.js",
|
|
47
47
|
"default": "./compose.js"
|
|
48
48
|
},
|
|
49
|
+
"./dynamodb": {
|
|
50
|
+
"types": "./dynamodb.d.ts",
|
|
51
|
+
"import": "./dynamodb.js",
|
|
52
|
+
"default": "./dynamodb.js"
|
|
53
|
+
},
|
|
54
|
+
"./dynamodb.js": {
|
|
55
|
+
"types": "./dynamodb.d.ts",
|
|
56
|
+
"import": "./dynamodb.js",
|
|
57
|
+
"default": "./dynamodb.js"
|
|
58
|
+
},
|
|
59
|
+
"./eventBridge": {
|
|
60
|
+
"types": "./eventBridge.d.ts",
|
|
61
|
+
"import": "./eventBridge.js",
|
|
62
|
+
"default": "./eventBridge.js"
|
|
63
|
+
},
|
|
64
|
+
"./eventBridge.js": {
|
|
65
|
+
"types": "./eventBridge.d.ts",
|
|
66
|
+
"import": "./eventBridge.js",
|
|
67
|
+
"default": "./eventBridge.js"
|
|
68
|
+
},
|
|
49
69
|
"./factory": {
|
|
50
70
|
"types": "./factory.d.ts",
|
|
51
71
|
"import": "./factory.js",
|
|
@@ -66,6 +86,16 @@
|
|
|
66
86
|
"import": "./index.js",
|
|
67
87
|
"default": "./index.js"
|
|
68
88
|
},
|
|
89
|
+
"./s3": {
|
|
90
|
+
"types": "./s3.d.ts",
|
|
91
|
+
"import": "./s3.js",
|
|
92
|
+
"default": "./s3.js"
|
|
93
|
+
},
|
|
94
|
+
"./s3.js": {
|
|
95
|
+
"types": "./s3.d.ts",
|
|
96
|
+
"import": "./s3.js",
|
|
97
|
+
"default": "./s3.js"
|
|
98
|
+
},
|
|
69
99
|
"./schedule": {
|
|
70
100
|
"types": "./schedule.d.ts",
|
|
71
101
|
"import": "./schedule.js",
|
|
@@ -76,6 +106,16 @@
|
|
|
76
106
|
"import": "./schedule.js",
|
|
77
107
|
"default": "./schedule.js"
|
|
78
108
|
},
|
|
109
|
+
"./ses": {
|
|
110
|
+
"types": "./ses.d.ts",
|
|
111
|
+
"import": "./ses.js",
|
|
112
|
+
"default": "./ses.js"
|
|
113
|
+
},
|
|
114
|
+
"./ses.js": {
|
|
115
|
+
"types": "./ses.d.ts",
|
|
116
|
+
"import": "./ses.js",
|
|
117
|
+
"default": "./ses.js"
|
|
118
|
+
},
|
|
79
119
|
"./sns": {
|
|
80
120
|
"types": "./sns.d.ts",
|
|
81
121
|
"import": "./sns.js",
|
package/s3.d.ts
ADDED
package/s3.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { compose } from './compose.js';
|
|
2
|
+
import { withError } from './wrapper/error.js';
|
|
3
|
+
import { withLogger } from './wrapper/logger.js';
|
|
4
|
+
import { withTimeout } from './wrapper/timeout.js';
|
|
5
|
+
import { withContext } from './wrapper/context.js';
|
|
6
|
+
import { withSmoke } from './wrapper/smoke.js';
|
|
7
|
+
export const s3 = compose(withError(), withLogger(), withTimeout(), withContext(), withSmoke());
|
package/ses.d.ts
ADDED
package/ses.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { compose } from './compose.js';
|
|
2
|
+
import { withError } from './wrapper/error.js';
|
|
3
|
+
import { withLogger } from './wrapper/logger.js';
|
|
4
|
+
import { withTimeout } from './wrapper/timeout.js';
|
|
5
|
+
import { withContext } from './wrapper/context.js';
|
|
6
|
+
import { withSmoke } from './wrapper/smoke.js';
|
|
7
|
+
export const ses = compose(withError(), withLogger(), withTimeout(), withContext(), withSmoke());
|
package/wrapper/headers.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { factory, streamFactory } from '../factory.js';
|
|
2
2
|
import { responseStream } from './stream.js';
|
|
3
|
+
const normalizeHeaders = (headers) => Object.fromEntries(Object.entries(headers ?? {}).map(([key, value]) => [key.toLowerCase(), value]));
|
|
3
4
|
const mergeHeaders = (result, options) => {
|
|
4
5
|
result.headers = {
|
|
5
|
-
...options,
|
|
6
|
-
...result.headers,
|
|
6
|
+
...normalizeHeaders(options),
|
|
7
|
+
...normalizeHeaders(result.headers),
|
|
7
8
|
};
|
|
8
9
|
return result;
|
|
9
10
|
};
|
|
@@ -13,5 +14,5 @@ export const withHeaders = factory(async (handler, args, options = {}) => {
|
|
|
13
14
|
});
|
|
14
15
|
export const streamWithHeaders = streamFactory(async (handler, args, options = {}) => {
|
|
15
16
|
const [event, stream, context] = args;
|
|
16
|
-
await handler(event, responseStream(stream, { headers: options }), context);
|
|
17
|
+
await handler(event, responseStream(stream, { headers: normalizeHeaders(options) }), context);
|
|
17
18
|
});
|
package/wrapper/stream.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
const getContentType = (headers) =>
|
|
1
|
+
const getContentType = (headers) => {
|
|
2
|
+
const contentType = Object.entries(headers ?? {}).find(([key]) => key.toLowerCase() === 'content-type')?.[1];
|
|
3
|
+
return typeof contentType === 'string' ? contentType : undefined;
|
|
4
|
+
};
|
|
2
5
|
export const responseStream = (stream, metadata = {}) => {
|
|
3
6
|
const runtimeStream = globalThis.awslambda?.HttpResponseStream?.from?.(stream, {
|
|
4
7
|
headers: metadata.headers,
|
|
@@ -9,7 +12,7 @@ export const responseStream = (stream, metadata = {}) => {
|
|
|
9
12
|
}
|
|
10
13
|
const contentType = getContentType(metadata.headers);
|
|
11
14
|
if (contentType) {
|
|
12
|
-
stream.setContentType?.(
|
|
15
|
+
stream.setContentType?.(contentType);
|
|
13
16
|
}
|
|
14
17
|
return stream;
|
|
15
18
|
};
|