Scope
Scopes in Alchemy are hierarchical containers that organize resources and other scopes, similar to a file system.
// Scope hierarchyapp (Application Scope)├── dev (Stage Scope)│ ├── api (Nested Scope)│ └── database (Resource)└── prod (Stage Scope)
Application Scope
Section titled “Application Scope”The top-level scope created using the alchemy()
function:
import alchemy from "alchemy";
// Create root scopeconst app = await alchemy("my-app");
// Create a resource in this scopeconst file = await File("config", { path: "./config.json", content: "{}" });
State directory structure:
.alchemy/ my-app/ # Application scope $USER/ # Default stage (username) config.json
Stage Scope
Section titled “Stage Scope”A scope directly under the application scope for separating environments:
// Create app with explicit stageconst app = await alchemy("my-app", { stage: "prod"});
// Resource in prod stageconst database = await Database("main", { /* props */ });
.alchemy/ my-app/ prod/ ## Stage scope main.json
Resource Scope
Section titled “Resource Scope”Each resource gets its own scope for managing child resources:
export const WebApp = Resource( "my::WebApp", async function (this, id, props) { // Child resources automatically scoped to this WebApp const database = await Database("db", {}); const apiGateway = await ApiGateway("api", {});
return this({ id, url: apiGateway.url, dbConnectionString: database.connectionString }); });
// Usageconst app = await WebApp("my-app", {});
.alchemy/ my-app/ dev/ my-app.json my-app/ # Resource scope db.json api.json
Nested Scope
Section titled “Nested Scope”Create custom nested scopes to organize related resources:
// Create nested scopesawait alchemy.run("backend", async () => { await ApiGateway("api", {}); await Function("handler", {});});
await alchemy.run("frontend", async () => { await Bucket("assets", {});});
.alchemy/ my-app/ dev/ backend/ api.json handler.json frontend/ assets.json
Scope Finalization
Section titled “Scope Finalization”When finalized, scopes delete any orphaned resources (resources in state but not in code):
const app = await alchemy("my-app");
await Bucket("assets", {});// If a previously existing resource is removed from code,// it will be deleted during finalization
await app.finalize(); // Manual finalization
Application scopes need manual finalization, but nested scopes finalize automatically when their execution completes.
Test Scope
Section titled “Test Scope”Alchemy provides isolated test scopes that automatically clean up after tests:
import { alchemy } from "../../src/alchemy";import "../../src/test/bun";
// Create test scope from filenameconst test = alchemy.test(import.meta, { prefix: BRANCH_PREFIX});
// Each test gets an isolated sub-scopetest("create resource", async (scope) => { const resource = await Resource("test-resource", {}); expect(resource.id).toBeTruthy(); // Resources auto-cleaned when test completes});
Example from Cloudflare Worker tests:
import { alchemy } from "../../src/alchemy";import { Worker } from "../../src/cloudflare/worker";import "../../src/test/bun";import { BRANCH_PREFIX } from "../util";
const test = alchemy.test(import.meta, { prefix: BRANCH_PREFIX });
describe("Worker Resource", () => { test("create worker", async (scope) => { const worker = await Worker(`${BRANCH_PREFIX}-test-worker`, { script: "// Worker code", format: "esm", });
expect(worker.id).toBeTruthy(); });});
For more details on testing with Alchemy, see Testing in Alchemy.