effortless-aws 0.32.0 → 0.32.1
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 +5 -12
- package/dist/runtime/wrap-api.js +45 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,15 +13,8 @@ npm install effortless-aws
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { defineApi } from "effortless-aws";
|
|
15
15
|
|
|
16
|
-
export const hello = defineApi({
|
|
17
|
-
|
|
18
|
-
get: {
|
|
19
|
-
"/": async () => ({
|
|
20
|
-
status: 200,
|
|
21
|
-
body: { message: "Hello!" },
|
|
22
|
-
}),
|
|
23
|
-
},
|
|
24
|
-
});
|
|
16
|
+
export const hello = defineApi({ basePath: "/hello" })
|
|
17
|
+
.get("/", async ({ ok }) => ok({ message: "Hello!" }));
|
|
25
18
|
```
|
|
26
19
|
|
|
27
20
|
## Handlers
|
|
@@ -39,9 +32,9 @@ export const hello = defineApi({
|
|
|
39
32
|
## Features
|
|
40
33
|
|
|
41
34
|
- **Infrastructure from code** — export a handler, get the AWS resources
|
|
42
|
-
- **Typed everything** — `defineTable<Order
|
|
43
|
-
- **Cross-handler deps** —
|
|
44
|
-
- **SSM params** —
|
|
35
|
+
- **Typed everything** — `defineTable<Order>()` gives you typed `put()`, typed `deps.orders.get()`, typed `record.new`
|
|
36
|
+
- **Cross-handler deps** — `.deps(() => ({ orders }))` auto-wires IAM and injects a typed `TableClient`
|
|
37
|
+
- **SSM params** — `.config(({ defineSecret }) => ...)` fetches secrets from Parameter Store at cold start
|
|
45
38
|
- **Static files** — `static: ["templates/*.ejs"]` bundles files into the Lambda ZIP
|
|
46
39
|
- **Cold start caching** — `setup` factory runs once per cold start, cached across invocations
|
|
47
40
|
|
package/dist/runtime/wrap-api.js
CHANGED
|
@@ -48,9 +48,37 @@ var unauthorized = () => ({
|
|
|
48
48
|
headers: { "Content-Type": "application/json" },
|
|
49
49
|
body: JSON.stringify({ error: "Unauthorized" })
|
|
50
50
|
});
|
|
51
|
-
var
|
|
52
|
-
|
|
53
|
-
)
|
|
51
|
+
var extractParamNames = (pattern) => {
|
|
52
|
+
const names = [];
|
|
53
|
+
pattern.replace(/\{(\w+)\}/g, (_, name) => {
|
|
54
|
+
names.push(name);
|
|
55
|
+
return "";
|
|
56
|
+
});
|
|
57
|
+
return names;
|
|
58
|
+
};
|
|
59
|
+
var patternToRegex = (pattern) => {
|
|
60
|
+
const escaped = pattern.replace(
|
|
61
|
+
/[.*+?^${}()|[\]\\]/g,
|
|
62
|
+
(ch) => ch === "{" || ch === "}" ? ch : `\\${ch}`
|
|
63
|
+
);
|
|
64
|
+
const withParams = escaped.replace(/\{(\w+)\}/g, "([^/]+)");
|
|
65
|
+
return new RegExp(`^${withParams}$`);
|
|
66
|
+
};
|
|
67
|
+
var findRoute = (routes, method, relativePath) => {
|
|
68
|
+
for (const r of routes) {
|
|
69
|
+
if (!(r.method === method || r.method === "GET" && method === "HEAD")) continue;
|
|
70
|
+
if (r.path === relativePath) return { entry: r, params: {} };
|
|
71
|
+
const regex = patternToRegex(r.path);
|
|
72
|
+
const match = relativePath.match(regex);
|
|
73
|
+
if (match) {
|
|
74
|
+
const names = extractParamNames(r.path);
|
|
75
|
+
const params = {};
|
|
76
|
+
for (let i = 0; i < names.length; i++) params[names[i]] = decodeURIComponent(match[i + 1]);
|
|
77
|
+
return { entry: r, params };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return void 0;
|
|
81
|
+
};
|
|
54
82
|
var wrapApi = (handler) => {
|
|
55
83
|
const rt = createHandlerRuntime(handler, "api", handler.__spec.lambda?.logLevel ?? "info", () => ({ ok, fail }));
|
|
56
84
|
const basePath = handler.__spec.basePath;
|
|
@@ -85,9 +113,21 @@ var wrapApi = (handler) => {
|
|
|
85
113
|
const method = event.requestContext?.http?.method ?? event.httpMethod ?? "GET";
|
|
86
114
|
const path = event.requestContext?.http?.path ?? event.path ?? "/";
|
|
87
115
|
const headers = event.headers ?? {};
|
|
88
|
-
const query = event.queryStringParameters ?? {};
|
|
89
|
-
const params = event.pathParameters ?? {};
|
|
90
116
|
const body = parseBody(event.body, event.isBase64Encoded ?? false);
|
|
117
|
+
const logInput = { method, path, query: event.queryStringParameters ?? {}, body };
|
|
118
|
+
const relativePath = extractRelativePath(path);
|
|
119
|
+
if (!relativePath) {
|
|
120
|
+
rt.logExecution(startTime, logInput, { status: 404 });
|
|
121
|
+
return notFound();
|
|
122
|
+
}
|
|
123
|
+
const routeMatch = findRoute(routes, method, relativePath);
|
|
124
|
+
if (!routeMatch) {
|
|
125
|
+
rt.logExecution(startTime, logInput, { status: 404 });
|
|
126
|
+
return notFound();
|
|
127
|
+
}
|
|
128
|
+
const { entry, params: routeParams } = routeMatch;
|
|
129
|
+
const query = event.queryStringParameters ?? {};
|
|
130
|
+
const params = { ...event.pathParameters ?? {}, ...routeParams };
|
|
91
131
|
const merged = {
|
|
92
132
|
...query,
|
|
93
133
|
...typeof body === "object" && body !== null ? body : {},
|
|
@@ -102,17 +142,6 @@ var wrapApi = (handler) => {
|
|
|
102
142
|
body,
|
|
103
143
|
rawBody: event.body
|
|
104
144
|
};
|
|
105
|
-
const logInput = { method, path, query, body };
|
|
106
|
-
const relativePath = extractRelativePath(req.path);
|
|
107
|
-
if (!relativePath) {
|
|
108
|
-
rt.logExecution(startTime, logInput, { status: 404 });
|
|
109
|
-
return notFound();
|
|
110
|
-
}
|
|
111
|
-
const entry = findRoute(routes, req.method, relativePath);
|
|
112
|
-
if (!entry) {
|
|
113
|
-
rt.logExecution(startTime, logInput, { status: 404 });
|
|
114
|
-
return notFound();
|
|
115
|
-
}
|
|
116
145
|
const cookieHeader = req.headers["cookie"] ?? req.headers["Cookie"] ?? "";
|
|
117
146
|
let authCookie;
|
|
118
147
|
if (cookieHeader) {
|