effortless-aws 0.6.0 → 0.7.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-AHRNISIY.js → chunk-5L76NICW.js} +47 -113
- package/dist/cli/index.js +2358 -1939
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +338 -389
- package/dist/index.js +1512 -95
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-app.js +30 -25
- package/dist/runtime/wrap-fifo-queue.js +37 -33
- package/dist/runtime/wrap-http.js +31 -27
- package/dist/runtime/wrap-table-stream.js +48 -44
- package/package.json +2 -1
package/dist/runtime/wrap-app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createHandlerRuntime
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-5L76NICW.js";
|
|
4
4
|
|
|
5
5
|
// src/runtime/wrap-app.ts
|
|
6
6
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -61,37 +61,42 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
61
61
|
]);
|
|
62
62
|
var wrapApp = (handler) => {
|
|
63
63
|
const { dir, index: indexFile = "index.html", spa = false } = handler.config;
|
|
64
|
-
const rt = createHandlerRuntime({}, "app");
|
|
64
|
+
const rt = createHandlerRuntime({}, "app", handler.config.logLevel ?? "error");
|
|
65
65
|
const baseDir = join(process.cwd(), dir);
|
|
66
66
|
return async (event) => {
|
|
67
67
|
const startTime = Date.now();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
filePath =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
rt.patchConsole();
|
|
69
|
+
try {
|
|
70
|
+
let filePath = event.pathParameters?.["file"] ?? "";
|
|
71
|
+
if (!filePath || filePath.endsWith("/")) {
|
|
72
|
+
filePath = filePath + indexFile;
|
|
73
|
+
}
|
|
74
|
+
const fullPath = resolve(baseDir, filePath);
|
|
75
|
+
if (!fullPath.startsWith(baseDir)) {
|
|
76
|
+
return {
|
|
77
|
+
statusCode: 403,
|
|
78
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
79
|
+
body: "<!DOCTYPE html><html><body><h1>403 Forbidden</h1></body></html>"
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (existsSync(fullPath)) {
|
|
83
|
+
return serveFile(fullPath, filePath, rt, startTime);
|
|
84
|
+
}
|
|
85
|
+
if (spa && !extname(filePath)) {
|
|
86
|
+
const spaPath = join(baseDir, indexFile);
|
|
87
|
+
if (existsSync(spaPath)) {
|
|
88
|
+
return serveFile(spaPath, indexFile, rt, startTime);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
rt.logError(startTime, { path: filePath }, "File not found");
|
|
74
92
|
return {
|
|
75
|
-
statusCode:
|
|
93
|
+
statusCode: 404,
|
|
76
94
|
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
77
|
-
body:
|
|
95
|
+
body: `<!DOCTYPE html><html><body><h1>404 Not Found</h1><p>${filePath}</p></body></html>`
|
|
78
96
|
};
|
|
97
|
+
} finally {
|
|
98
|
+
rt.restoreConsole();
|
|
79
99
|
}
|
|
80
|
-
if (existsSync(fullPath)) {
|
|
81
|
-
return serveFile(fullPath, filePath, rt, startTime);
|
|
82
|
-
}
|
|
83
|
-
if (spa && !extname(filePath)) {
|
|
84
|
-
const spaPath = join(baseDir, indexFile);
|
|
85
|
-
if (existsSync(spaPath)) {
|
|
86
|
-
return serveFile(spaPath, indexFile, rt, startTime);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
rt.logError(startTime, { path: filePath }, "File not found");
|
|
90
|
-
return {
|
|
91
|
-
statusCode: 404,
|
|
92
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
93
|
-
body: `<!DOCTYPE html><html><body><h1>404 Not Found</h1><p>${filePath}</p></body></html>`
|
|
94
|
-
};
|
|
95
100
|
};
|
|
96
101
|
};
|
|
97
102
|
function serveFile(fullPath, filePath, rt, startTime) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createHandlerRuntime
|
|
3
|
-
|
|
4
|
-
} from "../chunk-AHRNISIY.js";
|
|
2
|
+
createHandlerRuntime
|
|
3
|
+
} from "../chunk-5L76NICW.js";
|
|
5
4
|
|
|
6
5
|
// src/runtime/wrap-fifo-queue.ts
|
|
7
6
|
var parseMessages = (rawRecords, schema) => {
|
|
@@ -33,50 +32,55 @@ var wrapFifoQueue = (handler) => {
|
|
|
33
32
|
if (!handler.onMessage && !handler.onBatch) {
|
|
34
33
|
throw new Error("wrapFifoQueue requires a handler with onMessage or onBatch defined");
|
|
35
34
|
}
|
|
36
|
-
const rt = createHandlerRuntime(handler, "fifo-queue");
|
|
35
|
+
const rt = createHandlerRuntime(handler, "fifo-queue", handler.config.logLevel ?? "info");
|
|
37
36
|
const handleError = handler.onError ?? ((e) => console.error(`[effortless:${rt.handlerName}]`, e));
|
|
38
37
|
return async (event) => {
|
|
39
38
|
const startTime = Date.now();
|
|
40
|
-
|
|
41
|
-
const input = truncateForStorage({ messageCount: rawRecords.length });
|
|
42
|
-
let messages;
|
|
39
|
+
rt.patchConsole();
|
|
43
40
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
rt.logError(startTime, input, error);
|
|
48
|
-
return {
|
|
49
|
-
batchItemFailures: rawRecords.map((r) => ({ itemIdentifier: r.messageId }))
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
const shared = await rt.commonArgs();
|
|
53
|
-
const batchItemFailures = [];
|
|
54
|
-
if (handler.onBatch) {
|
|
41
|
+
const rawRecords = event.Records ?? [];
|
|
42
|
+
const input = { messageCount: rawRecords.length };
|
|
43
|
+
let messages;
|
|
55
44
|
try {
|
|
56
|
-
|
|
45
|
+
messages = parseMessages(rawRecords, handler.schema);
|
|
57
46
|
} catch (error) {
|
|
58
47
|
handleError(error);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
rt.logError(startTime, input, error);
|
|
49
|
+
return {
|
|
50
|
+
batchItemFailures: rawRecords.map((r) => ({ itemIdentifier: r.messageId }))
|
|
51
|
+
};
|
|
62
52
|
}
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
53
|
+
const shared = await rt.commonArgs();
|
|
54
|
+
const batchItemFailures = [];
|
|
55
|
+
if (handler.onBatch) {
|
|
66
56
|
try {
|
|
67
|
-
await
|
|
57
|
+
await handler.onBatch({ messages, ...shared });
|
|
68
58
|
} catch (error) {
|
|
69
59
|
handleError(error);
|
|
70
|
-
|
|
60
|
+
for (const message of messages) {
|
|
61
|
+
batchItemFailures.push({ itemIdentifier: message.messageId });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const onMessage = handler.onMessage;
|
|
66
|
+
for (const message of messages) {
|
|
67
|
+
try {
|
|
68
|
+
await onMessage({ message, ...shared });
|
|
69
|
+
} catch (error) {
|
|
70
|
+
handleError(error);
|
|
71
|
+
batchItemFailures.push({ itemIdentifier: message.messageId });
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
if (batchItemFailures.length > 0) {
|
|
76
|
+
rt.logError(startTime, input, `${batchItemFailures.length} message(s) failed`);
|
|
77
|
+
} else {
|
|
78
|
+
rt.logExecution(startTime, input, { processedCount: messages.length });
|
|
79
|
+
}
|
|
80
|
+
return { batchItemFailures };
|
|
81
|
+
} finally {
|
|
82
|
+
rt.restoreConsole();
|
|
73
83
|
}
|
|
74
|
-
if (batchItemFailures.length > 0) {
|
|
75
|
-
rt.logError(startTime, input, `${batchItemFailures.length} message(s) failed`);
|
|
76
|
-
} else {
|
|
77
|
-
rt.logExecution(startTime, input, { processedCount: messages.length });
|
|
78
|
-
}
|
|
79
|
-
return { batchItemFailures };
|
|
80
84
|
};
|
|
81
85
|
};
|
|
82
86
|
export {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createHandlerRuntime
|
|
3
|
-
|
|
4
|
-
} from "../chunk-AHRNISIY.js";
|
|
2
|
+
createHandlerRuntime
|
|
3
|
+
} from "../chunk-5L76NICW.js";
|
|
5
4
|
|
|
6
5
|
// src/runtime/wrap-http.ts
|
|
7
6
|
var CONTENT_TYPE_MAP = {
|
|
@@ -24,7 +23,7 @@ var parseBody = (body, isBase64) => {
|
|
|
24
23
|
}
|
|
25
24
|
};
|
|
26
25
|
var wrapHttp = (handler) => {
|
|
27
|
-
const rt = createHandlerRuntime(handler, "http");
|
|
26
|
+
const rt = createHandlerRuntime(handler, "http", handler.config.logLevel ?? "info");
|
|
28
27
|
const toResult = (r) => {
|
|
29
28
|
const resolved = r.contentType ? CONTENT_TYPE_MAP[r.contentType] : void 0;
|
|
30
29
|
const customContentType = resolved ?? r.headers?.["content-type"] ?? r.headers?.["Content-Type"];
|
|
@@ -52,33 +51,38 @@ var wrapHttp = (handler) => {
|
|
|
52
51
|
};
|
|
53
52
|
return async (event) => {
|
|
54
53
|
const startTime = Date.now();
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
rt.patchConsole();
|
|
55
|
+
try {
|
|
56
|
+
const req = {
|
|
57
|
+
method: event.requestContext?.http?.method ?? event.httpMethod ?? "GET",
|
|
58
|
+
path: event.requestContext?.http?.path ?? event.path ?? "/",
|
|
59
|
+
headers: event.headers ?? {},
|
|
60
|
+
query: event.queryStringParameters ?? {},
|
|
61
|
+
params: event.pathParameters ?? {},
|
|
62
|
+
body: parseBody(event.body, event.isBase64Encoded ?? false),
|
|
63
|
+
rawBody: event.body
|
|
64
|
+
};
|
|
65
|
+
const input = { method: req.method, path: req.path, query: req.query, body: req.body };
|
|
66
|
+
const args = { req };
|
|
67
|
+
if (handler.schema) {
|
|
68
|
+
try {
|
|
69
|
+
args.data = handler.schema(req.body);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
rt.logError(startTime, input, error);
|
|
72
|
+
return handler.onError ? toResult(handler.onError(error, req)) : defaultError(error, 400);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
Object.assign(args, await rt.commonArgs());
|
|
67
76
|
try {
|
|
68
|
-
|
|
77
|
+
const response = await handler.onRequest(args);
|
|
78
|
+
rt.logExecution(startTime, input, response.body);
|
|
79
|
+
return toResult(response);
|
|
69
80
|
} catch (error) {
|
|
70
81
|
rt.logError(startTime, input, error);
|
|
71
|
-
return handler.onError ? toResult(handler.onError(error, req)) : defaultError(error,
|
|
82
|
+
return handler.onError ? toResult(handler.onError(error, req)) : defaultError(error, 500);
|
|
72
83
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
const response = await handler.onRequest(args);
|
|
77
|
-
rt.logExecution(startTime, input, response.body);
|
|
78
|
-
return toResult(response);
|
|
79
|
-
} catch (error) {
|
|
80
|
-
rt.logError(startTime, input, error);
|
|
81
|
-
return handler.onError ? toResult(handler.onError(error, req)) : defaultError(error, 500);
|
|
84
|
+
} finally {
|
|
85
|
+
rt.restoreConsole();
|
|
82
86
|
}
|
|
83
87
|
};
|
|
84
88
|
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createHandlerRuntime,
|
|
3
|
-
createTableClient
|
|
4
|
-
|
|
5
|
-
} from "../chunk-AHRNISIY.js";
|
|
3
|
+
createTableClient
|
|
4
|
+
} from "../chunk-5L76NICW.js";
|
|
6
5
|
|
|
7
6
|
// src/runtime/wrap-table-stream.ts
|
|
8
7
|
import { unmarshall } from "@aws-sdk/util-dynamodb";
|
|
@@ -42,7 +41,7 @@ var wrapTableStream = (handler) => {
|
|
|
42
41
|
if (!handler.onRecord && !handler.onBatch) {
|
|
43
42
|
throw new Error("wrapTableStream requires a handler with onRecord or onBatch defined");
|
|
44
43
|
}
|
|
45
|
-
const rt = createHandlerRuntime(handler, "table");
|
|
44
|
+
const rt = createHandlerRuntime(handler, "table", handler.config.logLevel ?? "info");
|
|
46
45
|
const handleError = handler.onError ?? ((e) => console.error(`[effortless:${rt.handlerName}]`, e));
|
|
47
46
|
let selfClient = null;
|
|
48
47
|
const getSelfClient = () => {
|
|
@@ -54,61 +53,66 @@ var wrapTableStream = (handler) => {
|
|
|
54
53
|
};
|
|
55
54
|
return async (event) => {
|
|
56
55
|
const startTime = Date.now();
|
|
57
|
-
|
|
58
|
-
const input = truncateForStorage({ recordCount: rawRecords.length });
|
|
59
|
-
let records;
|
|
60
|
-
let sequenceNumbers;
|
|
56
|
+
rt.patchConsole();
|
|
61
57
|
try {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return { batchItemFailures: rawRecords.map((r) => r.dynamodb?.SequenceNumber).filter((s) => !!s).map((seq) => ({ itemIdentifier: seq })) };
|
|
67
|
-
}
|
|
68
|
-
const shared = { ...await rt.commonArgs(), table: getSelfClient() };
|
|
69
|
-
const batchItemFailures = [];
|
|
70
|
-
if (handler.onBatch) {
|
|
58
|
+
const rawRecords = event.Records ?? [];
|
|
59
|
+
const input = { recordCount: rawRecords.length };
|
|
60
|
+
let records;
|
|
61
|
+
let sequenceNumbers;
|
|
71
62
|
try {
|
|
72
|
-
|
|
63
|
+
({ records, sequenceNumbers } = parseRecords(rawRecords, handler.schema));
|
|
73
64
|
} catch (error) {
|
|
74
65
|
handleError(error);
|
|
75
|
-
|
|
66
|
+
rt.logError(startTime, input, error);
|
|
67
|
+
return { batchItemFailures: rawRecords.map((r) => r.dynamodb?.SequenceNumber).filter((s) => !!s).map((seq) => ({ itemIdentifier: seq })) };
|
|
76
68
|
}
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
const onRecord = handler.onRecord;
|
|
81
|
-
for (const record of records) {
|
|
69
|
+
const shared = { ...await rt.commonArgs(), table: getSelfClient() };
|
|
70
|
+
const batchItemFailures = [];
|
|
71
|
+
if (handler.onBatch) {
|
|
82
72
|
try {
|
|
83
|
-
|
|
84
|
-
if (result !== void 0) results.push(result);
|
|
73
|
+
await handler.onBatch({ records, ...shared });
|
|
85
74
|
} catch (error) {
|
|
86
75
|
handleError(error);
|
|
87
|
-
|
|
88
|
-
const seq = sequenceNumbers.get(record);
|
|
89
|
-
if (seq) batchItemFailures.push({ itemIdentifier: seq });
|
|
76
|
+
batchItemFailures.push(...collectFailures(records, sequenceNumbers));
|
|
90
77
|
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
78
|
+
} else {
|
|
79
|
+
const results = [];
|
|
80
|
+
const failures = [];
|
|
81
|
+
const onRecord = handler.onRecord;
|
|
82
|
+
for (const record of records) {
|
|
83
|
+
try {
|
|
84
|
+
const result = await onRecord({ record, ...shared });
|
|
85
|
+
if (result !== void 0) results.push(result);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
handleError(error);
|
|
88
|
+
failures.push({ record, error });
|
|
98
89
|
const seq = sequenceNumbers.get(record);
|
|
99
|
-
if (seq
|
|
100
|
-
|
|
90
|
+
if (seq) batchItemFailures.push({ itemIdentifier: seq });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (handler.onBatchComplete) {
|
|
94
|
+
try {
|
|
95
|
+
await handler.onBatchComplete({ results, failures, ...shared });
|
|
96
|
+
} catch (error) {
|
|
97
|
+
handleError(error);
|
|
98
|
+
for (const record of records) {
|
|
99
|
+
const seq = sequenceNumbers.get(record);
|
|
100
|
+
if (seq && !batchItemFailures.some((f) => f.itemIdentifier === seq)) {
|
|
101
|
+
batchItemFailures.push({ itemIdentifier: seq });
|
|
102
|
+
}
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
}
|
|
107
|
+
if (batchItemFailures.length > 0) {
|
|
108
|
+
rt.logError(startTime, input, `${batchItemFailures.length} record(s) failed`);
|
|
109
|
+
} else {
|
|
110
|
+
rt.logExecution(startTime, input, { processedCount: records.length });
|
|
111
|
+
}
|
|
112
|
+
return { batchItemFailures };
|
|
113
|
+
} finally {
|
|
114
|
+
rt.restoreConsole();
|
|
105
115
|
}
|
|
106
|
-
if (batchItemFailures.length > 0) {
|
|
107
|
-
rt.logError(startTime, input, `${batchItemFailures.length} record(s) failed`);
|
|
108
|
-
} else {
|
|
109
|
-
rt.logExecution(startTime, input, { processedCount: records.length });
|
|
110
|
-
}
|
|
111
|
-
return { batchItemFailures };
|
|
112
116
|
};
|
|
113
117
|
};
|
|
114
118
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effortless-aws",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Code-first AWS Lambda framework",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-apigatewayv2": "^3.975.0",
|
|
36
36
|
"@aws-sdk/client-cloudfront": "^3.989.0",
|
|
37
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.990.0",
|
|
37
38
|
"@aws-sdk/client-dynamodb": "^3.975.0",
|
|
38
39
|
"@aws-sdk/client-iam": "^3.975.0",
|
|
39
40
|
"@aws-sdk/client-lambda": "^3.975.0",
|