10 steps to start building your own Serverless Plugin using Typescript.
Tags: serverless, typescript, npm, node
Published: 2020-08-25 21:22:00

---
title: 10 steps to start building your own Serverless Plugin using Typescript.
published: true
description: How to get set up developing your own serverless plugin with Typescript
tags: serverless, typescript, npm, node
---

I've found building things with serverless really fun, and after skimming the surface of the documentation trying to build my own plugin, I wanted to start off my development using typescript, here's how I did it.

##### Step 1:

Setup your npm module to build the serverless plugin.

```sh
$ mkdir my-cool-plugin
$ cd my-cool-plugin
$ serverless create --template plugin
$ ls
index.js // <- What serverless made us.
```

##### Step 2:

Run npm init so we get ourselves a package.json.

```sh
$ npm init
# Whilst we're here, lets initialize git and add a .gitignore file and add node_modules to it.
$ git init
$ echo "node_modules" >> .gitignore
```

##### Step 3:

Add typescript as a dependency along with `@types/node`. We can init typescript so we get our `tsconfig.json` file.

```sh
$ npm i typescript --save-dev
$ npm i @types/node --save-dev
$ node_modules/typescript/bin/tsc --init
```

##### Step 4:

Add a `tsc` build script to our `package.json`.

```json
{
  "scripts": {
    "build": "tsc ./src/index.ts"
  },
}
```

> Good thing to note here is that scripts inside your `package.json` will look inside `node_modules`. That's why in step 3 I had to specify `node_modules/typescript/bin/tsc` when initialising.

##### Step 5:

Create our `src` folder with a basic `index.ts` file in.

```sh
$ mkdir src
$ echo "console.log('hello typescript')" >> src/index.ts
```

##### Step 6: (Totally optional)

Check it's all working!

```sh
$ npm run build
> my-cool-plugin@1.0.0 build /Users/karltaylor/code/my-cool-plugin
> tsc ./src/index.ts
```

You would now have an `index.js` inside your `src` folder which has been compiled from typescript to normal javascript. But the `src` directory isn't exactly where we want it.

##### Step 7:

Add a `rootDir` and `outDir` to our `tsconfig.json` and a watch script to our `package.json` to re-compile our files on save.

In our `tsconfig.json`:

```json
{
  "compilerOptions": {
    "rootDir": "./src"
    "outDir": "./dist",
  }
}
```

And our `package.json`:

```json
{
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w"
  },
}
```

##### Step 8:

Let's copy the contents of the `index.js` file that serverless gave us when we created in step 1 into our `index.ts` file.

You will be inundated with plenty of errors in the console that we now need to go and fix...

Now, unfortunately, after a lot of digging, I couldn't find the specific types for building a serverless _plugin_. But there is a @types/serverless file. To combat all the errors, your `index.ts` should look something like this:

```typescript
import Serverless from "serverless";

class ServerlessPlugin {
  serverless: Serverless;
  options: any;

  commands: {};
  hooks: { [key: string]: Function }

  constructor(serverless: Serverless, options: any) {
    this.serverless = serverless;
    this.options = options;

    this.commands = {
      welcome: {
        usage: "Helps you start your first Serverless plugin",
        lifecycleEvents: ["hello", "world"],
        options: {
          message: {
            usage:
              "Specify the message you want to deploy " +
              "(e.g. \"--message 'My Message'\" or \"-m 'My Message'\")",
            required: true,
            shortcut: "m",
          },
        },
      },
    };

    this.hooks = {
      "before:welcome:hello": this.beforeWelcome.bind(this),
      "welcome:hello": this.welcomeUser.bind(this),
      "welcome:world": this.displayHelloMessage.bind(this),
      "after:welcome:world": this.afterHelloWorld.bind(this),
    };
  }

  beforeWelcome() {
    this.serverless.cli.log("Hello from Serverless!");
  }

  welcomeUser() {
    this.serverless.cli.log("Your message:");
  }

  displayHelloMessage() {
    this.serverless.cli.log(`${this.options.message}`);
  }

  afterHelloWorld() {
    this.serverless.cli.log("Please come again!");
  }
}

module.exports = ServerlessPlugin;
```

Running `yarn build` in the console should successfully build your `index.ts` severless plugin boilerplate into `dist/index.js`

##### Step 9

Let's create a new `serverless` project in a new directory.

```sh
$ ~/code mkdir my-serverless-test-directory
$ ~/code cd my-serverless-test-directory
$ ~/code/my-serverless-test-directory npm init
$ ~/code/my-serverless-test-directory serverless create --template=hello-world
```

Let's install our npm module locally simply by referencing its absolute or relative path:

```sh
$ ~/code/my-serverless-test-directory npm i --save-dev ~/code/my-cool-plugin
```

Open up the `serverless.yml` file and add the name of your plugin to the `plugins` section:

```yml
# Welcome to serverless. Read the docs
# https://serverless.com/framework/docs/

# Serverless.yml is the configuration the CLI
# uses to deploy your code to your provider of choice

# The `service` block is the name of the service
service: my-serverless-test-directory

plugins:
  - my-cool-plugin # <------ Right here! 🚀

# The `provider` block defines where your service will be deployed
provider:
  name: aws
  runtime: nodejs12.x

# The `functions` block defines what code to deploy
functions:
  helloWorld:
    handler: handler.helloWorld
    # The `events` block defines how to trigger the handler.helloWorld code
    events:
      - http:
          path: hello-world
          method: get
          cors: true
```

##### Step 10

Let's run our serverless boilerplate plugin to check everything is working as it should:

```sh
$ ~/code/my-serverless-test-directory serverless welcome -m "Hello World Serverless Plugin in Typescript"
Serverless: Hello from Serverless!
Serverless: Your message:
Serverless: Hello World Serverless Plugin in Typescript
Serverless: Please come again!
```

And voila! Your compiled typescript serverless plugin is working!

Personally I've found there is a distinct lack of documentation for building Serverless Plugins, I am very much developing in the dark and figuring out what things do what, but it's very fun to play with.

Feel free to [follow me on twitter](https://twitter.com/karltaylor_) where I tweet about more tech-related adventures.