Skip to content

Runtime composition

Pure definition operations run without infrastructure. Durable workflows use the Sapa service Layer and require host-owned capabilities.

Compose Layers once at your runtime entrypoint. The shape is:

import { Sapa } from "@byfungsi/sapa";
import { Layer } from "effect";
import {
clockIdsAndSnapshotProtection,
providerRegistry,
storageAndHistory,
} from "./runtime-capabilities.js";
const runtimeLayer = Sapa.layer.pipe(
Layer.provideMerge(storageAndHistory),
Layer.provideMerge(providerRegistry),
Layer.provideMerge(clockIdsAndSnapshotProtection),
);

The named Layers are application-owned composition values, not exports from @byfungsi/sapa. Their exact requirements are inferred from Sapa.layer.

Use configured constructors when installed offers depend on optional behavior:

  • Sapa.makeConfigured for an exact capability manifest.
  • Sapa.makeWithDownloads for download assets and bounded URL policy.
  • Sapa.makeWithLicensing for cryptography and license issuance policy.
  • PostpaidAccessPolicies.layer for merchant-owned postpaid access decisions.

Store parameterized Layer instances before reusing them. Effect memoizes Layers by reference identity; calling the same constructor twice creates two Layer instances and may acquire resources twice.

Keep request-bound handles and capability Layers request-scoped. A Cloudflare Worker, server request, or job execution should build one coherent runtime for that boundary rather than sharing request-specific resources globally.

@byfungsi/sapa publishes framework contracts and orchestration. Concrete database, provider, email, and deployment adapters are not selected by the facade and are not implied by importing it. In 0.1.0, those adapters are not published as separate public npm packages. Consumers can use all pure definition and validation APIs immediately; durable workflows require a host deployment that supplies the capability Layers.