const handler = createServer({
economy,
ports,
authenticate: async (request) => {
const userId = await verifyToken(request.headers.get('authorization'));
return userId === null ? null : { kind: 'user', userId }; // null answers 401
},
});
HTTP service for the routes, codec, and webhook gate.
HTTP entry point for an Economy: takes a Fetch
Request, returns aResponse. Uses only Fetch globals (no Node APIs), so it runs on Node, Bun, Deno, and Cloudflare Workers.Routes these paths, 404s the rest:
POST /submitreads one operation from the JSON body, runs it, returns the result.POST /instances/:scope/purchase(only withinstancesconfigured) hands an in-world purchase to the scope's fast-lane session — the transport an unprivileged game server calls.POST /webhooks/:providerverifies the callback, then hands it to the injected handler.GET /healthzreports liveness without touching storage.GET /readyzreports readiness via one cheap store-touching read through the economy.A thrown EconomyError becomes an RFC 9457 problem+json response: statusForError maps the status,
titlecarries the caller-safe message, and the stablecodeandretryableride as extensions.detail,cause, and stack never leave the server./submitauthenticates throughauthenticatewhen configured; every body reads under a byte ceiling and deadline; CORS stays off unlesscorslists origins.Single-submit on purpose:
Economy.submitBatchand the submit coalescer are in-process surface for the host composing the economy, not a route — a shared batch transaction cannot carry each request's own correlation id.