Skip to content

Commit a63bd0d

Browse files
committed
add recommendations & typescript sections to readme
1 parent cb97da7 commit a63bd0d

File tree

2 files changed

+133
-7
lines changed

2 files changed

+133
-7
lines changed

README.md

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ Lambda Hooks help avoid repeated logic in your lambda functions. Use some of the
66

77
## Principles
88

9-
- Zero dependancies
10-
- Fast & simple to use
11-
- First class support for TypeScript & modern JavaScript
9+
- Zero dependancies 🚫
10+
- Fast & simple to use 🛤
11+
- First class support for TypeScript & ES7+ JavaScript 🤓
1212

1313
## Example
1414

@@ -48,15 +48,15 @@ _TypeScript types are included_ 🧰
4848

4949
## Usage
5050

51-
1. Import/require the package
51+
1. Require the package
5252

5353
```javascript
54-
const useHooks = require('lambda-hooks')
54+
const { useHooks } = require('lambda-hooks')
5555
```
5656

5757
2. Call useHooks with the hooks that you want to use. There's 3 types of hooks that are executed either before the lambda execution, after or if an error occurs.
5858

59-
Note that the order of the hooks matters, they are executed one by one from the first hook in the before array.
59+
Note that the order of the hooks matters, they are executed one by one starting from the first hook in the before array, then your lambda function is invoked, then through all hooks in the after array. If at any point an error occurs, execution is directed towards the onError hooks array.
6060

6161
Also, notice that we are invoking the hooks when they are passed in, this is deliberate and will make more sense when we get to a more complex example later.
6262

@@ -163,3 +163,109 @@ Woah calm down, actually there are a few rules ☝️
163163
2. The returned function (HookHandler) must be async or return a promise
164164
3. The HookHandler accepts the state object as input and must return the state object
165165
4. Your lambda function must be async
166+
167+
## Recommendations
168+
169+
> _"with great power, comes great responsibility"_ - someone, somewhere
170+
171+
Here's a few recommendations that might make your life easier.
172+
173+
- **Export the withHooks function to share across related lambdas.** For example, all your API lambdas might utilise the same hooks, but, your DynamoDB stream lambdas might need to utilise a different set of hooks. Rather than repeating the useHooks call for each lambda, call once and share around the related lambdas...
174+
175+
```javascript
176+
// file: src/hooks/api.js
177+
export const withApiHooks = (lambda, { requestSchema } = {}) =>
178+
useHooks({
179+
before: [
180+
handleScheduledEvent(),
181+
logEvent(),
182+
parseEvent(),
183+
validateEventBody({ requestSchema }),
184+
],
185+
onError: [handleUnexpectedError()],
186+
})(lambda))
187+
188+
189+
// file: src/api/lambda.js
190+
const { withApiHooks } = require('../hooks/api')
191+
192+
...
193+
194+
const handler = async event => {...}
195+
196+
export const lambda = withApiHooks(handler, { requestSchema: schema })
197+
```
198+
199+
- **Write your own hooks.** It's really easy to do. And, if you're migrating an existing project over, the logic will barely change. Just remember that to create a hook, you need a function (HookCreator) that returns another function (HookHandler). The HookCreator takes an optional config object. The HookHandler takes the state as input and also returns the state. That is all you need to know!
200+
201+
Feel free to share any hooks you make by submitting a PR 😉and, here's a boilerplate hook (that does absolutely nothing) to get you started:
202+
203+
```javascript
204+
export const myNewHook = () => async state => {
205+
const { event, context } = state
206+
207+
// your custom hook logic here....
208+
209+
return state
210+
}
211+
```
212+
213+
- **Use TypeScript.** I bet some of you JS folk are sick of hearing about it. But, once you get over the hump, it makes coding a lot more enjoyable, honestly. Speaking of which...
214+
215+
## TypeScript 🙌
216+
217+
```typescript
218+
import { useHooks,
219+
handleScheduledEvent,
220+
handleUnexpectedError,
221+
logEvent,
222+
parseEvent,
223+
validateEventBody,
224+
} from 'lambda-hooks'
225+
226+
const handler = async (event: APIGatewayProxyEvent, context: Context) => {...}
227+
228+
export const lambda = useHooks({
229+
before: [
230+
handleScheduledEvent(),
231+
logEvent(),
232+
parseEvent(),
233+
],
234+
onError: [handleUnexpectedError()],
235+
})(handler)
236+
```
237+
238+
Here's some types for more clarity on the explanations above. Note, you don't need to copy & paste these, this is just for comprehension, any types you need can be imported from the package.
239+
240+
```typescript
241+
interface Hooks {
242+
before?: HookHandler[]
243+
after?: HookHandler[]
244+
onError?: HookHandler[]
245+
}
246+
247+
type UseHooks = (hooks: Hooks) => WithHooks
248+
249+
type WithHooks = (lambda: any) => (event: any, context: Context) => Promise<any>
250+
251+
type HookCreator<Config = {}> = (config?: Config) => HookHandler
252+
253+
type HookHandler = (state: State) => Promise<State>
254+
```
255+
256+
Now let's get to an example of a hook written in TypeScript. Often when building with lambdas you'll want to keep some of your lambdas warm to avoid cold starts, but if you're doing this, remember to check and quit immediately otherwise you're wasting 💰. That's what this hook does...
257+
258+
```typescript
259+
import { HookCreator } from 'lambda-hooks'
260+
261+
export const handleScheduledEvent: HookCreator = () => async state => {
262+
const { event } = state
263+
264+
if (event['detail-type'] === 'Scheduled Event') {
265+
state.exit = true
266+
state.response = { statusCode: 200 }
267+
}
268+
269+
return state
270+
}
271+
```

package.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,27 @@
2929
"hooks",
3030
"middleware",
3131
"plugin",
32-
"serverless"
32+
"serverless",
33+
"AWS",
34+
"middy",
35+
"serverless express",
36+
"cloud",
37+
"functions",
38+
"adapter",
39+
"pipeline",
40+
"api",
41+
"validation",
42+
"nodejs",
43+
"AWS Lambda",
44+
"API Gateway",
45+
"DynamoDB",
46+
"s3",
47+
"SQS",
48+
"streams",
49+
"web framework",
50+
"serverless library",
51+
"json",
52+
"schema"
3353
],
3454
"author": "James Sweetland",
3555
"license": "MIT",

0 commit comments

Comments
 (0)