SST

SST (Serverless Stack Toolkit) is a framework that simplifies building serverless applications on AWS and Cloudflare. It provides a high-level abstraction over cloud resources, making it easier to define and deploy serverless infrastructure.

Unlike other infrastructure-as-code tools that create their own languages, SST uses TypeScript to define your infrastructure. This offers advantages like developer familiarity, code reuse, and type safety.

Deploying to Cloudflare

npm init -y
npx sst@latest init
npm install

Modify the run(){ } part of sst.config.ts as following, which will add a worker:

async run() {
  const worker = new sst.cloudflare.Worker("MyWorker", {
    handler: "./index.ts",
    url: true,
  });

  return {
    api: worker.url,
  }
}

Add a index.ts:

export default {
    async fetch(req: Request) {
        return new Response(`hello!`)
    },
}

Create Cloudflare API Token

Go to https://dash.cloudflare.com/profile/api-tokens, click "Create Token", choose the template "Edit Cloudflare Workers". Save the token to .env:

export CLOUDFLARE_API_TOKEN=m5wULRSb2TWym8zlgl1f5FZfhbmCZP3IrChvQWth

Deploy

Start dev mode:

npx sst dev

This will give you an URL of you API for dev purpose, and sst will keep it continusly deployed as code changes.

To make a production deployment, run:

npx sst deploy --stage production

This will give you a different URL as production API.

Modify sst.config.ts to add a new bucket and link it to the worker:

async run() {
  const bucket = new sst.cloudflare.Bucket("MyBucket")
  
  const worker = new sst.cloudflare.Worker("MyWorker", {
    handler: "./index.ts",
    link: [bucket],
    url: true,
  });

  return {
    api: worker.url,
  }
}

Modify index.ts to use the bucket:

import { Resource } from "sst"

export default {
  async fetch(req: Request) {
    if (req.method == "PUT") {
      const key = crypto.randomUUID()
      await Resource.MyBucket.put(key, req.body, {
        httpMetadata: {
          contentType: req.headers.get("content-type"),
        },
      })
      return new Response(`Object created with key: ${key}`)
    }

    if (req.method == "GET") {
      const url = new URL(req.url)
      const result = await Resource.MyBucket.get(url.pathname.slice(1))
      return new Response(result.body, {
        headers: {
          "content-type": result.httpMetadata.contentType,
        },
      })
    }
  },
}

Verify the API

curl -X PUT --header "Content-Type: application/json" -d @package.json <URL>
curl -i <URL>/<key>

Why SST

As the about example shows, SST allows you to define your infrastructure as code, eliminating the need to manually create resources like workers and buckets through the cloud console or wrangler. This significantly streamlines your development process.