effortless-aws 0.28.0 → 0.30.0
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/dist/{chunk-EZG3NX42.js → chunk-ISJC6CHC.js} +24 -21
- package/dist/index.d.ts +595 -716
- package/dist/index.js +313 -129
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-api.js +69 -95
- package/dist/runtime/wrap-bucket.js +10 -6
- package/dist/runtime/wrap-fifo-queue.js +18 -10
- package/dist/runtime/wrap-table-stream.js +45 -39
- package/package.json +6 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createHandlerRuntime
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-ISJC6CHC.js";
|
|
4
4
|
|
|
5
5
|
// src/runtime/wrap-fifo-queue.ts
|
|
6
6
|
var parseMessages = (rawRecords, schema) => {
|
|
@@ -29,19 +29,22 @@ var parseMessages = (rawRecords, schema) => {
|
|
|
29
29
|
return messages;
|
|
30
30
|
};
|
|
31
31
|
var wrapFifoQueue = (handler) => {
|
|
32
|
-
if (!handler.onMessage && !handler.
|
|
33
|
-
throw new Error("wrapFifoQueue requires a handler with onMessage or
|
|
32
|
+
if (!handler.onMessage && !handler.onMessageBatch) {
|
|
33
|
+
throw new Error("wrapFifoQueue requires a handler with onMessage or onMessageBatch defined");
|
|
34
34
|
}
|
|
35
35
|
const rt = createHandlerRuntime(handler, "fifo-queue", handler.__spec.lambda?.logLevel ?? "info");
|
|
36
36
|
const handleError = handler.onError ?? (({ error }) => console.error(`[effortless:${rt.handlerName}]`, error));
|
|
37
37
|
return async (event) => {
|
|
38
38
|
const startTime = Date.now();
|
|
39
39
|
rt.patchConsole();
|
|
40
|
-
let
|
|
40
|
+
let ctxProps = {};
|
|
41
41
|
try {
|
|
42
42
|
const rawRecords = event.Records ?? [];
|
|
43
43
|
const input = { messageCount: rawRecords.length };
|
|
44
|
-
|
|
44
|
+
const common = await rt.commonArgs();
|
|
45
|
+
const ctx = common.ctx;
|
|
46
|
+
ctxProps = ctx && typeof ctx === "object" ? { ...ctx } : {};
|
|
47
|
+
const shared = { ...ctxProps };
|
|
45
48
|
let messages;
|
|
46
49
|
try {
|
|
47
50
|
messages = parseMessages(rawRecords, handler.schema);
|
|
@@ -53,9 +56,14 @@ var wrapFifoQueue = (handler) => {
|
|
|
53
56
|
};
|
|
54
57
|
}
|
|
55
58
|
const batchItemFailures = [];
|
|
56
|
-
if (handler.
|
|
59
|
+
if (handler.onMessageBatch) {
|
|
57
60
|
try {
|
|
58
|
-
await handler.
|
|
61
|
+
const result = await handler.onMessageBatch({ messages, ...shared });
|
|
62
|
+
if (result?.failures) {
|
|
63
|
+
for (const id of result.failures) {
|
|
64
|
+
batchItemFailures.push({ itemIdentifier: id });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
59
67
|
} catch (error) {
|
|
60
68
|
handleError({ error, ...shared });
|
|
61
69
|
for (const message of messages) {
|
|
@@ -80,11 +88,11 @@ var wrapFifoQueue = (handler) => {
|
|
|
80
88
|
}
|
|
81
89
|
return { batchItemFailures };
|
|
82
90
|
} finally {
|
|
83
|
-
if (handler.
|
|
91
|
+
if (handler.onCleanup) {
|
|
84
92
|
try {
|
|
85
|
-
await handler.
|
|
93
|
+
await handler.onCleanup(ctxProps);
|
|
86
94
|
} catch (e) {
|
|
87
|
-
console.error(`[effortless:${rt.handlerName}]
|
|
95
|
+
console.error(`[effortless:${rt.handlerName}] onCleanup error`, e);
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
98
|
rt.restoreConsole();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createHandlerRuntime,
|
|
3
3
|
createTableClient
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ISJC6CHC.js";
|
|
5
5
|
|
|
6
6
|
// src/runtime/wrap-table-stream.ts
|
|
7
7
|
import { unmarshall } from "@aws-sdk/util-dynamodb";
|
|
@@ -36,20 +36,13 @@ var parseRecords = (rawRecords, schema) => {
|
|
|
36
36
|
}
|
|
37
37
|
return { records, sequenceNumbers };
|
|
38
38
|
};
|
|
39
|
-
var collectFailures = (records, sequenceNumbers) => {
|
|
40
|
-
const failures = [];
|
|
41
|
-
for (const record of records) {
|
|
42
|
-
const seq = sequenceNumbers.get(record);
|
|
43
|
-
if (seq) failures.push({ itemIdentifier: seq });
|
|
44
|
-
}
|
|
45
|
-
return failures;
|
|
46
|
-
};
|
|
47
39
|
var ENV_DEP_SELF = "EFF_DEP_SELF";
|
|
48
40
|
var wrapTableStream = (handler) => {
|
|
49
|
-
if (!handler.onRecord && !handler.
|
|
50
|
-
throw new Error("wrapTableStream requires a handler with onRecord or
|
|
41
|
+
if (!handler.onRecord && !handler.onRecordBatch) {
|
|
42
|
+
throw new Error("wrapTableStream requires a handler with onRecord or onRecordBatch defined");
|
|
51
43
|
}
|
|
52
44
|
const tagField = handler.__spec.tagField ?? "tag";
|
|
45
|
+
const concurrency = handler.__spec.concurrency ?? 1;
|
|
53
46
|
let selfClient = null;
|
|
54
47
|
const getSelfClient = () => {
|
|
55
48
|
if (selfClient) return selfClient;
|
|
@@ -67,11 +60,14 @@ var wrapTableStream = (handler) => {
|
|
|
67
60
|
return async (event) => {
|
|
68
61
|
const startTime = Date.now();
|
|
69
62
|
rt.patchConsole();
|
|
70
|
-
let
|
|
63
|
+
let ctxProps = {};
|
|
71
64
|
try {
|
|
72
65
|
const rawRecords = event.Records ?? [];
|
|
73
66
|
const input = { recordCount: rawRecords.length };
|
|
74
|
-
|
|
67
|
+
const common = await rt.commonArgs();
|
|
68
|
+
const ctx = common.ctx;
|
|
69
|
+
ctxProps = ctx && typeof ctx === "object" ? { ...ctx } : {};
|
|
70
|
+
const shared = { ...ctxProps };
|
|
75
71
|
let records;
|
|
76
72
|
let sequenceNumbers;
|
|
77
73
|
try {
|
|
@@ -82,37 +78,47 @@ var wrapTableStream = (handler) => {
|
|
|
82
78
|
return { batchItemFailures: rawRecords.map((r) => r.dynamodb?.SequenceNumber).filter((s) => !!s).map((seq) => ({ itemIdentifier: seq })) };
|
|
83
79
|
}
|
|
84
80
|
const batchItemFailures = [];
|
|
85
|
-
|
|
81
|
+
const frozenBatch = Object.freeze(records);
|
|
82
|
+
if (handler.onRecordBatch) {
|
|
86
83
|
try {
|
|
87
|
-
await handler.
|
|
84
|
+
const result = await handler.onRecordBatch({ records: frozenBatch, ...shared });
|
|
85
|
+
if (result?.failures) {
|
|
86
|
+
for (const seq of result.failures) {
|
|
87
|
+
batchItemFailures.push({ itemIdentifier: seq });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
88
90
|
} catch (error) {
|
|
89
91
|
handleError({ error, ...shared });
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
const results = [];
|
|
94
|
-
const failures = [];
|
|
95
|
-
const onRecord = handler.onRecord;
|
|
96
|
-
for (const record of records) {
|
|
97
|
-
try {
|
|
98
|
-
const result = await onRecord({ record, ...shared });
|
|
99
|
-
if (result !== void 0) results.push(result);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
handleError({ error, ...shared });
|
|
102
|
-
failures.push({ record, error });
|
|
92
|
+
for (const record of records) {
|
|
103
93
|
const seq = sequenceNumbers.get(record);
|
|
104
94
|
if (seq) batchItemFailures.push({ itemIdentifier: seq });
|
|
105
95
|
}
|
|
106
96
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
97
|
+
} else {
|
|
98
|
+
const onRecord = handler.onRecord;
|
|
99
|
+
if (concurrency <= 1) {
|
|
100
|
+
for (const record of records) {
|
|
101
|
+
try {
|
|
102
|
+
await onRecord({ record, batch: frozenBatch, ...shared });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
handleError({ error, ...shared });
|
|
113
105
|
const seq = sequenceNumbers.get(record);
|
|
114
|
-
if (seq
|
|
115
|
-
|
|
106
|
+
if (seq) batchItemFailures.push({ itemIdentifier: seq });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
for (let i = 0; i < records.length; i += concurrency) {
|
|
111
|
+
const chunk = records.slice(i, i + concurrency);
|
|
112
|
+
const results = await Promise.allSettled(
|
|
113
|
+
chunk.map((record) => onRecord({ record, batch: frozenBatch, ...shared }))
|
|
114
|
+
);
|
|
115
|
+
for (let j = 0; j < results.length; j++) {
|
|
116
|
+
const result = results[j];
|
|
117
|
+
const record = chunk[j];
|
|
118
|
+
if (result.status === "rejected") {
|
|
119
|
+
handleError({ error: result.reason, ...shared });
|
|
120
|
+
const seq = sequenceNumbers.get(record);
|
|
121
|
+
if (seq) batchItemFailures.push({ itemIdentifier: seq });
|
|
116
122
|
}
|
|
117
123
|
}
|
|
118
124
|
}
|
|
@@ -125,11 +131,11 @@ var wrapTableStream = (handler) => {
|
|
|
125
131
|
}
|
|
126
132
|
return { batchItemFailures };
|
|
127
133
|
} finally {
|
|
128
|
-
if (handler.
|
|
134
|
+
if (handler.onCleanup) {
|
|
129
135
|
try {
|
|
130
|
-
await handler.
|
|
136
|
+
await handler.onCleanup(ctxProps);
|
|
131
137
|
} catch (e) {
|
|
132
|
-
console.error(`[effortless:${rt.handlerName}]
|
|
138
|
+
console.error(`[effortless:${rt.handlerName}] onCleanup error`, e);
|
|
133
139
|
}
|
|
134
140
|
}
|
|
135
141
|
rt.restoreConsole();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effortless-aws",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Code-first AWS Lambda framework. Export handlers, deploy with one command.",
|
|
@@ -45,10 +45,13 @@
|
|
|
45
45
|
"@types/node": "^22.19.9",
|
|
46
46
|
"tsup": "^8.5.1",
|
|
47
47
|
"type-fest": "^4.22.1",
|
|
48
|
-
"typescript": "^5.9.3"
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vite-tsconfig-paths": "^6.1.1",
|
|
50
|
+
"vitest": "^4.0.18"
|
|
49
51
|
},
|
|
50
52
|
"scripts": {
|
|
51
53
|
"build": "tsup",
|
|
52
|
-
"typecheck": "tsc --noEmit"
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"test": "vitest run"
|
|
53
56
|
}
|
|
54
57
|
}
|