diff --git a/.eslintrc.js b/.eslintrc.js index 9eb13e8..18e4456 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,19 +1,18 @@ module.exports = { - parser: '@typescript-eslint/parser', // Specifies the ESLint parser - extends: [ - 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - parserOptions: { - ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features - sourceType: 'module', // Allows for the use of imports - }, - rules: { - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-var-requires': 'off', - }, + parser: '@typescript-eslint/parser', // Specifies the ESLint parser + extends: [ + 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin + 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + 'plugin:prettier/recommended' // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + ], + parserOptions: { + ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features + sourceType: 'module' // Allows for the use of imports + }, + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-non-null-assertion': 'off' + } } diff --git a/README.md b/README.md index 5f95a52..05be728 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ const withHooks = useHooks({ 3. useHooks returns a function withHooks. Pass your **async** lambda into the withHooks function to decorate your lambda and then export as normal. ```javascript -const handler = async (event, context) => {...} +const handler = async (event, context) => {...} exports.handler = withHooks(handler) ``` diff --git a/src/hooks/handleScheduledEvent.ts b/src/hooks/handleScheduledEvent.ts index 938e0c7..047c270 100644 --- a/src/hooks/handleScheduledEvent.ts +++ b/src/hooks/handleScheduledEvent.ts @@ -1,4 +1,4 @@ -import { HookCreator } from '../types/hooks' +import { HookCreator } from '../index' export const handleScheduledEvent: HookCreator = () => async state => { const { event } = state diff --git a/src/hooks/handleUnexpectedError.ts b/src/hooks/handleUnexpectedError.ts index 99120ae..d34ae73 100644 --- a/src/hooks/handleUnexpectedError.ts +++ b/src/hooks/handleUnexpectedError.ts @@ -1,4 +1,4 @@ -import { HookCreator } from '../types/hooks' +import { HookCreator } from '../index' export const handleUnexpectedError: HookCreator = () => async state => { const { error } = state diff --git a/src/hooks/logEvent.ts b/src/hooks/logEvent.ts index fd97c60..bbcd7b1 100644 --- a/src/hooks/logEvent.ts +++ b/src/hooks/logEvent.ts @@ -1,4 +1,4 @@ -import { HookCreator } from '../types/hooks' +import { HookCreator } from '../index' export const logEvent: HookCreator = () => async state => { console.log(`received event: ${state.event}`) diff --git a/src/hooks/parseEvent.ts b/src/hooks/parseEvent.ts index f290e7f..87ce527 100644 --- a/src/hooks/parseEvent.ts +++ b/src/hooks/parseEvent.ts @@ -1,4 +1,4 @@ -import { HookCreator } from '../types/hooks' +import { HookCreator } from '../index' export const parseEvent: HookCreator = () => async state => { const { event } = state diff --git a/src/hooks/validateEventBody.ts b/src/hooks/validateEventBody.ts index d20f457..d8c54c8 100644 --- a/src/hooks/validateEventBody.ts +++ b/src/hooks/validateEventBody.ts @@ -1,6 +1,6 @@ import { ObjectSchema } from 'yup' -import { HookCreator } from '../types/hooks' +import { HookCreator } from '../index' interface Config { requestSchema: ObjectSchema diff --git a/src/index.ts b/src/index.ts index de6f74c..14618b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,5 @@ import { Context } from 'aws-lambda' -import { Event, HooksObject, UseHooks, UseHooksState } from './types/hooks' -import { combineHooks } from './utils' -import { defaultHook } from './utils/defaultHook' - export { handleScheduledEvent, handleUnexpectedError, @@ -12,28 +8,62 @@ export { validateEventBody, } from './hooks' -export * from './types/hooks' +interface Hooks { + before?: HookHandler[] + after?: HookHandler[] + onError?: HookHandler[] +} + +type Response = any +type Event = any + +interface State { + event: Event + context: Context + exit: boolean + response?: Response + error?: Error +} /** - * Using the provided hooks create an `withHooks` higher order function - * @param hooks a variadic array of config objects containing the hooks to apply to your lambda. Each config object can contain `before`, `after` and `onError` arrays - * @returns WithHooks() function that wraps around your lambda + * @param config optional configuration object for this hook + * @returns HookHandler */ -export const useHooks: UseHooks = (...hooksArr) => { - if (!hooksArr) { - hooksArr = [defaultHook] - } +export type HookCreator = (config?: Config) => HookHandler +/** + * @param state a state object that might be manipulated by this function + * @param state.event event passed in from AWS + * @param state.context context passed in from AWS + * @param state.exit defaults to false, if set to true program will exit early after ivocation of this hook + * @param state.response returned when state.exit is set to true + * @param state.error exists only if there's an unhandled exception thrown inside a hook or the lambda + * @returns Promise + */ +type HookHandler = (state: State) => Promise - const hooks: HooksObject = combineHooks(hooksArr) +type UseHooks = (hooks: Hooks) => WithHooks +type WithHooks = (lambda: any) => (event: any, context: Context) => Promise +/** + * Using the provided hooks create an withHooks higher order function + * @param hooks a config object of the hooks to apply to your lambda + * @param hooks.before an array of hooks to run before the provided lambda + * @param hooks.after an array of hooks to run after the provided lambda + * @param hooks.onError an array of hooks to run only if there's an error during the execution + * @returns WithHooks() function that wraps around your lambda + */ +export const useHooks: UseHooks = (hooks: Hooks): WithHooks => { + if (!hooks.before) hooks.before = [] + if (!hooks.after) hooks.after = [] + if (!hooks.onError) hooks.onError = [] /** * Higher order function that takes a lambda function * as input and applies the hooks provided to useHooks() * @param lambda lambda function - * @returns supercharged lambda 🚀 + * @returns supercharged lambda 🚀 */ const withHooks = (lambda: any) => async (event: Event, context: Context) => { - let state: UseHooksState = { event, context, exit: false } + let state: State = { event, context, exit: false } try { for (const hook of hooks.before!) { diff --git a/src/types/hooks.ts b/src/types/hooks.ts deleted file mode 100644 index a74ced7..0000000 --- a/src/types/hooks.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Context } from 'aws-lambda' - -/** - * `before`: an array of hooks to run before the provided lambda - * - * `after` an array of hooks to run after the provided lambda - * - * `onError` an array of hooks to run only if there's an error during the execution - */ -export interface HooksObject { - before: HookHandler[] - after: HookHandler[] - onError: HookHandler[] -} - -export type PartialHooksObject = Partial - -/** - * @param config optional configuration object for this hook - * @returns HookHandler - */ -export type HookCreator = (config?: Config) => HookHandler - -export type Response = any -export type Event = any - -export interface UseHooksState { - event: Event - context: Context - exit: boolean - response?: Response - error?: Error -} - -/** - * @param state a state object that might be manipulated by this function - * @param state.event event passed in from AWS - * @param state.context context passed in from AWS - * @param state.exit defaults to false, if set to true program will exit early after ivocation of this hook - * @param state.response returned when state.exit is set to true - * @param state.error exists only if there's an unhandled exception thrown inside a hook or the lambda - * @returns Promise - */ -export type HookHandler = (state: UseHooksState) => Promise - -export type UseHooks = (...hooks: PartialHooksObject[]) => WithHooks -export type WithHooks = (lambda: any) => (event: any, context: Context) => Promise diff --git a/src/utils/defaultHook.ts b/src/utils/defaultHook.ts deleted file mode 100644 index e9acc0a..0000000 --- a/src/utils/defaultHook.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { HooksObject } from '../types/hooks' - -export const defaultHook: HooksObject = { - before: [], - after: [], - onError: [], -} diff --git a/src/utils/index.ts b/src/utils/index.ts deleted file mode 100644 index a92c8c7..0000000 --- a/src/utils/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { HooksObject, PartialHooksObject } from '../types/hooks' -import { defaultHook } from './defaultHook' - -/** - * Combine a number of hooksObjects into a single hooksObject - * @param hooks The hooks to be combined - */ -export const combineHooks = (hooks: PartialHooksObject[]): HooksObject => { - return hooks.reduce((result, hook) => { - // Add any missing properties - const newHook: HooksObject = { ...defaultHook, ...hook } - - // Combine the result and the current hooksObject - return { - before: [...result.before, ...newHook.before], - after: [...result.after, ...newHook.after], - onError: [...result.onError, ...newHook.onError], - } - }, defaultHook) -}