Skip to content

SST Integration

SST is an infrastructure-as-code framework that makes deploying to Cloudflare simple and type-safe. Corpus provides helper functions to streamline resource creation.

Installation

Terminal window
bun add @f0rbit/corpus

API Reference

createCorpusInfra(name, config?)

Creates resource name definitions for D1 database and R2 bucket.

import { createCorpusInfra } from '@f0rbit/corpus'
const corpus = createCorpusInfra('myapp')

Parameters:

ParameterTypeDescription
namestringBase prefix for resource names
configPartial<CorpusInfraConfig>Optional overrides

CorpusInfraConfig

type CorpusInfraConfig = {
name: string
bucket_name?: string // Override bucket name (default: `${name}Bucket`)
database_name?: string // Override database name (default: `${name}Db`)
}

CorpusInfra (Return Type)

type CorpusInfra = {
database: { name: string } // For SST resource constructor
bucket: { name: string } // For SST resource constructor
database_name: string // Raw name string
bucket_name: string // Raw name string
}

Complete Example

SST Config

sst.config.ts
import { createCorpusInfra } from '@f0rbit/corpus'
export default $config({
app(input) {
return {
name: 'my-app',
removal: input?.stage === 'production' ? 'retain' : 'remove',
home: 'cloudflare',
}
},
async run() {
const corpus = createCorpusInfra('corpus')
const db = new sst.cloudflare.D1(corpus.database.name)
const bucket = new sst.cloudflare.Bucket(corpus.bucket.name)
const worker = new sst.cloudflare.Worker('Api', {
handler: 'src/index.ts',
link: [db, bucket],
url: true,
})
return { url: worker.url }
},
})

Worker Code

src/index.ts
import { Resource } from 'sst'
import {
create_corpus,
create_cloudflare_backend,
define_store,
json_codec
} from '@f0rbit/corpus/cloudflare'
import { z } from 'zod'
const DataSchema = z.object({
id: z.string(),
content: z.string(),
updated_at: z.string(),
})
export default {
async fetch(request: Request): Promise<Response> {
const backend = create_cloudflare_backend({
d1: Resource.corpusDb,
r2: Resource.corpusBucket,
})
const corpus = create_corpus()
.with_backend(backend)
.with_store(define_store('data', json_codec(DataSchema)))
.build()
const result = await corpus.stores.data.put({
id: 'doc-1',
content: 'Hello from SST!',
updated_at: new Date().toISOString(),
})
if (!result.ok) {
return Response.json({ error: result.error }, { status: 500 })
}
return Response.json({ version: result.value.version })
},
}

Drizzle Migrations

Corpus schemas are exported for use with Drizzle Kit. Configure drizzle.config.ts:

import { defineConfig } from 'drizzle-kit'
export default defineConfig({
dialect: 'sqlite',
driver: 'd1-http',
schema: [
'./node_modules/@f0rbit/corpus/schema.js',
'./node_modules/@f0rbit/corpus/observations/schema.js',
],
out: './migrations',
})

Generate and apply migrations:

Terminal window
bunx drizzle-kit generate
wrangler d1 migrations apply <database-name>

Custom Resource Names

Override the default naming convention when needed:

const corpus = createCorpusInfra('myapp', {
database_name: 'MyCustomDatabase',
bucket_name: 'my-custom-bucket',
})
// corpus.database.name === 'MyCustomDatabase'
// corpus.bucket.name === 'my-custom-bucket'

See Also