Skip to content

Commit f3c17c8

Browse files
authored
feat: Http Api lambda handler (#86)
* feat: initial version of `makeApiLambda` * feat: implement fromHttpApi function * refactor: improve namespacing and example, add changeset * docs: missed jsdoc * docs: fix docgen flaws * test: cover 3 main event with tests * feat: more performant and effect native implementation * revert: back to initial implementation
1 parent ae67c59 commit f3c17c8

40 files changed

+1863
-237
lines changed

.changeset/gorgeous-phones-sin.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
"@effect-aws/lambda": minor
3+
---
4+
5+
add an option to make lambda handler from platform httpApi, for instance
6+
7+
```ts
8+
import { LambdaHandler } from "@effect-aws/lambda"
9+
import { HttpApi, HttpApiBuilder, HttpServer } from "@effect/platform"
10+
import { Layer } from "effect"
11+
12+
class MyApi extends HttpApi.make("api") {}
13+
14+
const MyApiLive = HttpApiBuilder.api(MyApi)
15+
16+
// ┌─── Handler<LambdaEvent, LambdaResult>
17+
//
18+
export const handler = LambdaHandler.fromHttpApi(
19+
Layer.mergeAll(
20+
MyApiLive,
21+
// you could also use NodeHttpServer.layerContext, depending on your
22+
// server's platform
23+
HttpServer.layerContext
24+
)
25+
)
26+
```

.projenrc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const lambda = new TypeScriptLibProject({
108108
description: "Effectful AWS Lambda handler",
109109
devDeps: [...effectDeps, "@types/aws-lambda"],
110110
peerDeps: commonPeerDeps,
111+
addExamples: true,
111112
});
112113

113114
new TypeScriptLibProject({

package.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/lambda/.gitattributes

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/lambda/.gitignore

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/lambda/.npmignore

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/lambda/.projen/files.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { LambdaHandler } from "@effect-aws/lambda";
2+
import {
3+
FetchHttpClient,
4+
HttpApi,
5+
HttpApiBuilder,
6+
HttpApiEndpoint,
7+
HttpApiGroup,
8+
HttpApiSchema,
9+
HttpClient,
10+
HttpClientResponse,
11+
HttpServer,
12+
} from "@effect/platform";
13+
import { Effect, Layer, Schema } from "effect";
14+
15+
const YahooResponse = Schema.Struct({
16+
chart: Schema.Struct({
17+
result: Schema.Array(Schema.Struct({
18+
indicators: Schema.Struct({
19+
quote: Schema.Array(Schema.Struct({
20+
close: Schema.Array(Schema.Number),
21+
high: Schema.Array(Schema.Number),
22+
low: Schema.Array(Schema.Number),
23+
open: Schema.Array(Schema.Number),
24+
volume: Schema.Array(Schema.Number),
25+
})),
26+
}),
27+
timestamp: Schema.Array(Schema.Number),
28+
})),
29+
}),
30+
});
31+
32+
const symbolParam = HttpApiSchema.param("symbol", Schema.String);
33+
34+
const getQuote = HttpApiEndpoint.get(
35+
"getQuote",
36+
)`/quote/${symbolParam}`.addSuccess(YahooResponse);
37+
38+
const quotesGroup = HttpApiGroup.make("quotes").add(getQuote);
39+
40+
const MyApi = HttpApi.make("MyApi").add(quotesGroup);
41+
42+
// Implement the "quotes" group
43+
const QuotesLive = HttpApiBuilder.group(
44+
MyApi,
45+
"quotes",
46+
(handlers) =>
47+
handlers.handle(
48+
"getQuote",
49+
({ path }) =>
50+
HttpClient.get(`https://query2.finance.yahoo.com/v8/finance/chart/${path.symbol}`, {
51+
urlParams: { interval: "1d" },
52+
}).pipe(
53+
Effect.andThen(HttpClientResponse.schemaBodyJson(YahooResponse)),
54+
Effect.orDie,
55+
),
56+
),
57+
);
58+
59+
// Provide the implementation for the API
60+
const MyApiLive = HttpApiBuilder.api(MyApi).pipe(
61+
Layer.provide(QuotesLive),
62+
Layer.provide(FetchHttpClient.layer),
63+
);
64+
65+
// Create the Lambda handler
66+
export const handler = LambdaHandler.fromHttpApi(
67+
Layer.mergeAll(
68+
MyApiLive,
69+
// you could also use NodeHttpServer.layerContext, depending on your
70+
// server's platform
71+
HttpServer.layerContext,
72+
),
73+
);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
service: example-app
2+
frameworkVersion: "3"
3+
4+
plugins: [serverless-esbuild]
5+
6+
provider:
7+
name: aws
8+
runtime: nodejs22.x
9+
region: eu-west-1
10+
11+
custom:
12+
esbuild:
13+
packager: pnpm
14+
15+
functions:
16+
api:
17+
handler: fromHttpApi.handler
18+
layers:
19+
- arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:53 # Needed for graceful shutdown
20+
events:
21+
- http:
22+
path: /{proxy+} # This will match all paths on the API Gateway level, so routing is handled by Effect HttpApi
23+
method: ANY

packages/lambda/package.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)