effortless-aws 0.28.0 → 0.29.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 +274 -378
- package/dist/index.js +66 -74
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-api.js +64 -92
- package/dist/runtime/wrap-bucket.js +9 -5
- package/dist/runtime/wrap-fifo-queue.js +17 -9
- package/dist/runtime/wrap-table-stream.js +44 -38
- package/package.json +6 -3
package/dist/runtime/wrap-api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AUTH_COOKIE_NAME,
|
|
3
3
|
createHandlerRuntime
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ISJC6CHC.js";
|
|
5
5
|
|
|
6
6
|
// src/runtime/wrap-api.ts
|
|
7
7
|
var CONTENT_TYPE_MAP = {
|
|
@@ -23,32 +23,6 @@ var parseBody = (body, isBase64) => {
|
|
|
23
23
|
return decoded;
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
-
var buildGetMatchers = (routes, basePath) => Object.entries(routes).map(([pattern, handler]) => {
|
|
27
|
-
const fullPattern = (basePath + pattern).replace(/\/\/+/g, "/");
|
|
28
|
-
const paramNames = [];
|
|
29
|
-
const regexStr = fullPattern.replace(/\{(\w+)\}/g, (_, name) => {
|
|
30
|
-
paramNames.push(name);
|
|
31
|
-
return "([^/]+)";
|
|
32
|
-
});
|
|
33
|
-
return {
|
|
34
|
-
regex: new RegExp(`^${regexStr}$`),
|
|
35
|
-
paramNames,
|
|
36
|
-
handler
|
|
37
|
-
};
|
|
38
|
-
});
|
|
39
|
-
var matchRoute = (matchers, path) => {
|
|
40
|
-
for (const matcher of matchers) {
|
|
41
|
-
const match = path.match(matcher.regex);
|
|
42
|
-
if (match) {
|
|
43
|
-
const params = {};
|
|
44
|
-
matcher.paramNames.forEach((name, i) => {
|
|
45
|
-
params[name] = match[i + 1];
|
|
46
|
-
});
|
|
47
|
-
return { handler: matcher.handler, params };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
51
|
-
};
|
|
52
26
|
var toResult = (r) => {
|
|
53
27
|
const resolved = r.contentType ? CONTENT_TYPE_MAP[r.contentType] : void 0;
|
|
54
28
|
const customContentType = resolved ?? r.headers?.["content-type"] ?? r.headers?.["Content-Type"];
|
|
@@ -74,14 +48,14 @@ var unauthorized = () => ({
|
|
|
74
48
|
headers: { "Content-Type": "application/json" },
|
|
75
49
|
body: JSON.stringify({ error: "Unauthorized" })
|
|
76
50
|
});
|
|
77
|
-
var
|
|
78
|
-
(
|
|
51
|
+
var findRoute = (routes, method, relativePath) => routes.find(
|
|
52
|
+
(r) => r.path === relativePath && (r.method === method || r.method === "GET" && method === "HEAD")
|
|
79
53
|
);
|
|
80
54
|
var wrapApi = (handler) => {
|
|
81
55
|
const rt = createHandlerRuntime(handler, "api", handler.__spec.lambda?.logLevel ?? "info");
|
|
82
56
|
const basePath = handler.__spec.basePath;
|
|
83
57
|
const isStream = handler.__spec.stream === true;
|
|
84
|
-
const
|
|
58
|
+
const routes = handler.routes ?? [];
|
|
85
59
|
const defaultError = (error, status) => {
|
|
86
60
|
console.error(`[effortless:${rt.handlerName}]`, error);
|
|
87
61
|
return toResult({
|
|
@@ -92,91 +66,89 @@ var wrapApi = (handler) => {
|
|
|
92
66
|
}
|
|
93
67
|
});
|
|
94
68
|
};
|
|
69
|
+
const extractRelativePath = (fullPath) => {
|
|
70
|
+
const prefix = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
71
|
+
if (!fullPath.startsWith(prefix)) return null;
|
|
72
|
+
const rest = fullPath.slice(prefix.length);
|
|
73
|
+
if (rest === "" || rest === "/") return "/";
|
|
74
|
+
if (!rest.startsWith("/")) return null;
|
|
75
|
+
return rest;
|
|
76
|
+
};
|
|
95
77
|
const handleRequest = async (event, streamCtx) => {
|
|
96
78
|
const startTime = Date.now();
|
|
97
79
|
rt.patchConsole();
|
|
98
80
|
let sharedArgs;
|
|
81
|
+
let ctxProps = {};
|
|
99
82
|
try {
|
|
83
|
+
const method = event.requestContext?.http?.method ?? event.httpMethod ?? "GET";
|
|
84
|
+
const path = event.requestContext?.http?.path ?? event.path ?? "/";
|
|
85
|
+
const headers = event.headers ?? {};
|
|
86
|
+
const query = event.queryStringParameters ?? {};
|
|
87
|
+
const params = event.pathParameters ?? {};
|
|
88
|
+
const body = parseBody(event.body, event.isBase64Encoded ?? false);
|
|
89
|
+
const merged = {
|
|
90
|
+
...query,
|
|
91
|
+
...typeof body === "object" && body !== null ? body : {},
|
|
92
|
+
...params
|
|
93
|
+
};
|
|
100
94
|
const req = {
|
|
101
|
-
method
|
|
102
|
-
path
|
|
103
|
-
headers
|
|
104
|
-
query
|
|
105
|
-
params
|
|
106
|
-
body
|
|
95
|
+
method,
|
|
96
|
+
path,
|
|
97
|
+
headers,
|
|
98
|
+
query,
|
|
99
|
+
params,
|
|
100
|
+
body,
|
|
107
101
|
rawBody: event.body
|
|
108
102
|
};
|
|
109
|
-
const
|
|
103
|
+
const logInput = { method, path, query, body };
|
|
104
|
+
const relativePath = extractRelativePath(req.path);
|
|
105
|
+
if (!relativePath) {
|
|
106
|
+
rt.logExecution(startTime, logInput, { status: 404 });
|
|
107
|
+
return notFound();
|
|
108
|
+
}
|
|
109
|
+
const entry = findRoute(routes, req.method, relativePath);
|
|
110
|
+
if (!entry) {
|
|
111
|
+
rt.logExecution(startTime, logInput, { status: 404 });
|
|
112
|
+
return notFound();
|
|
113
|
+
}
|
|
110
114
|
const cookieHeader = req.headers["cookie"] ?? req.headers["Cookie"] ?? "";
|
|
111
115
|
let authCookie;
|
|
112
116
|
if (cookieHeader) {
|
|
113
117
|
const match = cookieHeader.match(new RegExp(`(?:^|;\\s*)${AUTH_COOKIE_NAME}=([^;]+)`));
|
|
114
118
|
if (match) authCookie = match[1];
|
|
115
119
|
}
|
|
116
|
-
const authHeaderName =
|
|
120
|
+
const authHeaderName = "authorization";
|
|
117
121
|
const authHeader = req.headers[authHeaderName] ?? req.headers[authHeaderName.toLowerCase()] ?? void 0;
|
|
118
|
-
sharedArgs = await rt.commonArgs(authCookie, authHeader);
|
|
119
|
-
if (
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!auth.session && !isPublicPath(routePath, publicPaths) && !isPublicPath(req.path, publicPaths)) {
|
|
124
|
-
rt.logExecution(startTime, input, { status: 401 });
|
|
122
|
+
sharedArgs = await rt.commonArgs(authCookie, authHeader, req.headers);
|
|
123
|
+
if (sharedArgs.auth) {
|
|
124
|
+
const auth2 = sharedArgs.auth;
|
|
125
|
+
if (!auth2.session && !entry.public) {
|
|
126
|
+
rt.logExecution(startTime, logInput, { status: 401 });
|
|
125
127
|
return unauthorized();
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (response) {
|
|
140
|
-
rt.logExecution(startTime, input, response.body);
|
|
141
|
-
return toResult(response);
|
|
142
|
-
}
|
|
143
|
-
rt.logExecution(startTime, input, "[stream]");
|
|
144
|
-
return void 0;
|
|
145
|
-
} catch (error) {
|
|
146
|
-
rt.logError(startTime, input, error);
|
|
147
|
-
return handler.onError ? toResult(handler.onError({ error, req, ...sharedArgs })) : defaultError(error, 500);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (req.method === "POST" && handler.post) {
|
|
151
|
-
const args = { req, ...sharedArgs };
|
|
152
|
-
if (streamCtx) args.stream = streamCtx.stream;
|
|
153
|
-
if (handler.schema) {
|
|
154
|
-
try {
|
|
155
|
-
args.data = handler.schema(req.body);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
rt.logError(startTime, input, error);
|
|
158
|
-
return handler.onError ? toResult(handler.onError({ error, req, ...sharedArgs })) : defaultError(error, 400);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
const response = await handler.post(args);
|
|
163
|
-
if (response) {
|
|
164
|
-
rt.logExecution(startTime, input, response.body);
|
|
165
|
-
return toResult(response);
|
|
166
|
-
}
|
|
167
|
-
rt.logExecution(startTime, input, "[stream]");
|
|
168
|
-
return void 0;
|
|
169
|
-
} catch (error) {
|
|
170
|
-
rt.logError(startTime, input, error);
|
|
171
|
-
return handler.onError ? toResult(handler.onError({ error, req, ...sharedArgs })) : defaultError(error, 500);
|
|
130
|
+
const { ctx, auth, ...rest } = sharedArgs;
|
|
131
|
+
ctxProps = ctx && typeof ctx === "object" ? { ...ctx } : {};
|
|
132
|
+
delete ctxProps.auth;
|
|
133
|
+
const args = { ...ctxProps, req, input: merged, ...rest };
|
|
134
|
+
if (auth) args.auth = auth;
|
|
135
|
+
if (streamCtx) args.stream = streamCtx.stream;
|
|
136
|
+
try {
|
|
137
|
+
const response = await entry.onRequest(args);
|
|
138
|
+
if (response) {
|
|
139
|
+
rt.logExecution(startTime, logInput, response.body);
|
|
140
|
+
return toResult(response);
|
|
172
141
|
}
|
|
142
|
+
rt.logExecution(startTime, logInput, "[stream]");
|
|
143
|
+
return void 0;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
rt.logError(startTime, logInput, error);
|
|
146
|
+
return handler.onError ? toResult(handler.onError({ error, req, ...ctxProps })) : defaultError(error, 500);
|
|
173
147
|
}
|
|
174
|
-
rt.logExecution(startTime, input, { status: 404 });
|
|
175
|
-
return notFound();
|
|
176
148
|
} finally {
|
|
177
149
|
if (handler.onAfterInvoke && sharedArgs) {
|
|
178
150
|
try {
|
|
179
|
-
await handler.onAfterInvoke(
|
|
151
|
+
await handler.onAfterInvoke(ctxProps);
|
|
180
152
|
} catch (e) {
|
|
181
153
|
console.error(`[effortless:${rt.handlerName}] onAfterInvoke error`, e);
|
|
182
154
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createBucketClient,
|
|
3
3
|
createHandlerRuntime
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ISJC6CHC.js";
|
|
5
5
|
|
|
6
6
|
// src/runtime/wrap-bucket.ts
|
|
7
7
|
var ENV_DEP_SELF = "EFF_DEP_SELF";
|
|
@@ -26,11 +26,15 @@ var wrapBucket = (handler) => {
|
|
|
26
26
|
return async (event) => {
|
|
27
27
|
const startTime = Date.now();
|
|
28
28
|
rt.patchConsole();
|
|
29
|
-
let
|
|
29
|
+
let ctxProps = {};
|
|
30
30
|
try {
|
|
31
31
|
const rawRecords = event.Records ?? [];
|
|
32
32
|
const input = { recordCount: rawRecords.length };
|
|
33
|
-
|
|
33
|
+
const common = await rt.commonArgs();
|
|
34
|
+
const ctx = common.ctx;
|
|
35
|
+
ctxProps = ctx && typeof ctx === "object" ? { ...ctx } : {};
|
|
36
|
+
const bucket = getSelfClient();
|
|
37
|
+
const shared = { bucket, ...ctxProps };
|
|
34
38
|
let errorCount = 0;
|
|
35
39
|
for (const record of rawRecords) {
|
|
36
40
|
const bucketEvent = {
|
|
@@ -58,9 +62,9 @@ var wrapBucket = (handler) => {
|
|
|
58
62
|
rt.logExecution(startTime, input, { processedCount: rawRecords.length });
|
|
59
63
|
}
|
|
60
64
|
} finally {
|
|
61
|
-
if (handler.onAfterInvoke
|
|
65
|
+
if (handler.onAfterInvoke) {
|
|
62
66
|
try {
|
|
63
|
-
await handler.onAfterInvoke(
|
|
67
|
+
await handler.onAfterInvoke(ctxProps);
|
|
64
68
|
} catch (e) {
|
|
65
69
|
console.error(`[effortless:${rt.handlerName}] onAfterInvoke error`, e);
|
|
66
70
|
}
|
|
@@ -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,9 +88,9 @@ var wrapFifoQueue = (handler) => {
|
|
|
80
88
|
}
|
|
81
89
|
return { batchItemFailures };
|
|
82
90
|
} finally {
|
|
83
|
-
if (handler.onAfterInvoke
|
|
91
|
+
if (handler.onAfterInvoke) {
|
|
84
92
|
try {
|
|
85
|
-
await handler.onAfterInvoke(
|
|
93
|
+
await handler.onAfterInvoke(ctxProps);
|
|
86
94
|
} catch (e) {
|
|
87
95
|
console.error(`[effortless:${rt.handlerName}] onAfterInvoke error`, e);
|
|
88
96
|
}
|
|
@@ -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,9 +131,9 @@ var wrapTableStream = (handler) => {
|
|
|
125
131
|
}
|
|
126
132
|
return { batchItemFailures };
|
|
127
133
|
} finally {
|
|
128
|
-
if (handler.onAfterInvoke
|
|
134
|
+
if (handler.onAfterInvoke) {
|
|
129
135
|
try {
|
|
130
|
-
await handler.onAfterInvoke(
|
|
136
|
+
await handler.onAfterInvoke(ctxProps);
|
|
131
137
|
} catch (e) {
|
|
132
138
|
console.error(`[effortless:${rt.handlerName}] onAfterInvoke error`, e);
|
|
133
139
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effortless-aws",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.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
|
}
|