Skip to content

Serverless TypeScript template with batteries included

Notifications You must be signed in to change notification settings

mrdck/serverless-typescript-template

Repository files navigation

Serverless Typescript Project Starter

Install

Using serverless

serverless install --url https://github.com/mrdck/serverless-typescript-template --name serverless-application

Using git clone

git clone https://github.com/mrdck/serverless-typescript-template serverless-application
cd serverless-application
yarn

Running locally

This template comes with serverless-offline package for running serverless application against local setup.

yarn start

Testing

Following template leverages testing on Jest framework with serverless-plugin-test-helper for running tests against serverless handlers.

yarn test

Code below shows example of test for validating health endpoint

describe('handler', () => {
  test('returns 200 HTTP', async () => {
    const handler = health(new ApiGatewayEvent(), context, jest.fn())

    await expect(handler).resolves.toMatchObject({
      body:       ReasonPhrases.OK,
      statusCode: StatusCodes.OK,
    })
  })
})

Lint

ESLint is used as linter with ready configuration

yarn lint

In order to change ESLint rules please edit .eslintrc.yml file

Deployment

yarn deploy

Project Structure

├── package.json
├── README.md
├── serverless.yml
├── src
│   ├── common.ts
│   ├── foo.ts
│   ├── health.ts
│   └── middleware.ts
├── tests
│   ├── common.test.ts
│   ├── foo.test.ts
│   └── health.test.ts
├── tsconfig.json
└── yarn.lock

Dependency Injection (IoC)

Following template leverage Dependency Injection on inversify package that introduces Inversion of Control container. In src/common/container there is container component that serve purpose of Root Composite that hooks and instantiate all dependencies with container.

This approach allow easy access on handler level

// container with dependencies is available in context
export async function handler(_: APIGatewayProxyEvent, { container }: Context): Promise<APIGatewayProxyResult> {
  // get dependency bound to container
  const config = container.get<Config>(Config)

  if (config.foo) {
    // some foo logic
  }

  return response(StatusCodes.OK, ReasonPhrases.OK)
}

// handler needs to be decorated with middleware otherwise container is not bound
export const health = middleware(handler)

License

MIT