HTTP Handlers
HTTP routes are server-to-server routes, not caller-authenticated reducers. Their
context exposes the module database identity, timestamp, HTTP request data,
randomness, UUID helpers, and transaction-scoped DB access. It does not expose a
caller sender, caller identity, or connection id.
Declare routes in an StdbHttpGroup. Typed routes provide request and
response schemas; raw routes omit them and work directly with Request and
SyncResponse.
import * as Effect from "effect/Effect"import * as Stdb from "effect-spacetimedb"
const tokenRotation = Stdb.table("token_rotation", { columns: { userId: Stdb.string().primaryKey(), token: Stdb.string(), },})
const RotateTokenInput = Stdb.struct({ userId: Stdb.string() }).schemaconst RotateTokenOutput = Stdb.struct({ token: Stdb.string() }).schema
const Webhooks = Stdb.StdbHttpGroup.make("Webhooks") .prefix("/webhooks") .add(Stdb.StdbHttp.post("stripe_webhook", "/stripe")) .add( Stdb.StdbHttp.post("rotate_token", "/rotate", { request: RotateTokenInput, response: RotateTokenOutput, }), )
const Module = Stdb.StdbModule.make("app") .addTables(tokenRotation) .add(Webhooks)const { HttpTx, Db } = Module
const WebhooksLive = Stdb.StdbBuilder.group(Module, "Webhooks", { stripe_webhook: (request) => Effect.succeed(new Stdb.SyncResponse(request.text(), { status: 202 })), rotate_token: (args) => Effect.gen(function* () { const tx = yield* HttpTx return yield* tx.run( Effect.gen(function* () { const db = yield* Db const row = yield* db.token_rotation.userId.replace({ userId: args.userId, token: `token:${args.userId}`, }) return { token: row.token } }), ) }),})Use raw routes for GET or HEAD, query strings, custom auth headers, webhooks, and non-JSON bodies. Keep external side effects outside HTTP transaction bodies, just as you would for procedures.
effect-spacetimedb uses StdbHttpGroup plus
StdbBuilder.group(...) instead of exporting handler functions directly. Typed
post, put, and patch routes can also be projected to an Effect HttpApi.
Project Typed Routes To HttpApi
Section titled “Project Typed Routes To HttpApi”Typed post, put, and patch routes can also be projected into a canonical
Effect HttpApi. The STDB HTTP group becomes the HttpApiClient property key,
and the route name becomes the typed endpoint method.
import * as Effect from "effect/Effect"import * as HttpClient from "effect/unstable/http/HttpClient"import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"import * as HttpApiClient from "effect/unstable/httpapi/HttpApiClient"import * as Stdb from "effect-spacetimedb"
declare const uri: stringdeclare const databaseName: stringdeclare const token: stringdeclare const userId: string
const RotateTokenInput = Stdb.struct({ userId: Stdb.string() }).schemaconst RotateTokenOutput = Stdb.struct({ token: Stdb.string() }).schema
const Webhooks = Stdb.StdbHttpGroup.make("Webhooks").add( Stdb.StdbHttp.post("rotate_token", "/rotate", { request: RotateTokenInput, response: RotateTokenOutput, }),)
const Module = Stdb.StdbModule.make("app").add(Webhooks)const api = Stdb.toHttpApi(Module.spec)
const program = Effect.gen(function* () { const client = yield* HttpApiClient.make(api, { baseUrl: Stdb.httpApiBaseUrl({ uri, databaseName }), transformClient: HttpClient.mapRequest( HttpClientRequest.bearerToken(token), ), })
const response = yield* client.Webhooks.rotate_token({ payload: { userId }, })
return response.token})Not affiliated with SpacetimeDB (Clockwork Laboratories) or Effect (Effectful Technologies).