Scope
A Scope represents a hierarchical container for resources in Alchemy. Scopes manage resource state, lifecycle, and provide utilities for resource management. The root scope is created by calling alchemy(), and child scopes can be created using alchemy.run().
Properties
The identifier for this scope level.
The name of the root application.
The parent scope, or undefined if this is the root scope.
The stage name for this scope (e.g., “dev”, “prod”).
phase
'up' | 'destroy' | 'read'
The current lifecycle phase.
Whether resources should be simulated locally.
Whether to watch for changes and automatically update resources.
Whether to suppress log output.
Whether to force resource updates.
Whether to adopt existing resources.
The password used for encrypting secrets in this scope.
resources
Map<string, PendingResource>
Map of all resources in this scope.
The root scope of the application.
Methods
createPhysicalName()
Creates a physical name for a resource based on the application, stage, and resource ID.
createPhysicalName(
id: string,
delimiter?: string,
maxLength?: number
): string
The delimiter to use between name components.
Maximum length for the physical name. If exceeded, components will be truncated.
Returns: A physical name in the format {appName}-{scope-chain}-{id}-{stage}
Example:
const name = scope.createPhysicalName("bucket");
// Returns: "my-app-bucket-dev"
const name = scope.createPhysicalName("bucket", "_", 20);
// Returns: "my_app_bucket_dev" (truncated if needed)
fqn()
Generates a fully qualified name for a resource.
fqn(resourceID: string): string
Returns: Fully qualified name in the format {appName}/{scope-chain}/{resourceID}
Example:
const fqn = scope.fqn("my-resource");
// Returns: "my-app/dev/my-resource"
has()
Checks if a resource with the given ID exists in the scope’s state.
has(id: string, type?: string): Promise<boolean>
Optional resource type to match.
Returns: true if the resource exists (and matches the type if provided)
get()
Retrieves a value from the scope’s data storage.
get<T>(key: string): Promise<T>
Returns: The stored value.
set()
Stores a value in the scope’s data storage.
set<T>(key: string, value: T): Promise<void>
delete()
Deletes a value from the scope’s data storage.
delete(key: string): Promise<void>
run()
Runs a function within this scope’s context.
run<T>(fn: (scope: Scope) => Promise<T>): Promise<T>
The async function to run within the scope.
Returns: The result of the function.
Example:
const result = await scope.run(async (scope) => {
const resource = await MyResource("id", { prop: "value" });
return resource.id;
});
finalize()
Finalizes the scope, destroying orphaned resources and cleaning up.
finalize(options?: { force?: boolean; noop?: boolean }): Promise<void>
Force finalization even if not the root scope.
Skip actual deletion operations.
Example:
const app = await alchemy("my-app");
// ... create resources ...
await app.finalize();
defer()
Defers execution of a function until the scope finalizes.
defer<T>(fn: () => Promise<T>): Promise<T>
The async function to defer.
Returns: A promise that resolves when the deferred function completes.
Example:
const result = scope.defer(async () => {
// This runs during finalize
return await someAsyncOperation();
});
// Later...
await scope.finalize();
const value = await result; // Now available
spawn()
Spawns an idempotent process managed by the scope.
spawn<E extends ((line: string) => string | undefined) | undefined>(
id: string,
options: {
command: string;
args?: string[];
cwd?: string;
env?: Record<string, string>;
extract?: E;
}
): Promise<E extends undefined ? undefined : string>
Unique identifier for the process.
Working directory for the command.
Function to extract a value from process output lines.
Returns: Extracted value if extract is provided, otherwise undefined.
Example:
const url = await scope.spawn("dev-server", {
command: "npm",
args: ["run", "dev"],
extract: (line) => {
const match = line.match(/Local:\s+(https?:\/\/.+)/);
return match?.[1];
}
});
console.log(`Server running at ${url}`);
exec()
Executes a command and returns the result.
exec(
id: string,
command: string
): Promise<{ exitCode: number; stdout: string; stderr: string }>
Unique identifier for logging.
Returns: Object containing exit code and output.
onCleanup()
Registers a cleanup function to run when the process exits.
onCleanup(fn: () => Promise<void>): void
The async cleanup function.
Example:
const proc = spawn('server', ['--port', '3000']);
scope.onCleanup(async () => {
proc.kill();
await waitForExit(proc);
});
Static Methods
Scope.current
Gets the current scope from the async context.
static get current(): Scope
Returns: The current scope.
Throws: Error if not running within an Alchemy scope.
Example:
const scope = Scope.current;
console.log(scope.stage);
Scope.root
Gets the root scope of the current application.
Returns: The root scope.
Examples
Creating a Root Scope
import { alchemy } from "alchemy";
const app = await alchemy("my-app", {
stage: "prod",
password: process.env.SECRET_PASSPHRASE
});
console.log(app.stage); // "prod"
console.log(app.appName); // "my-app"
await app.finalize();
Creating Child Scopes
const app = await alchemy("my-app");
await alchemy.run("api", async (apiScope) => {
const worker = await Worker("api-worker", {
entrypoint: "./src/api.ts"
});
console.log(apiScope.fqn("api-worker")); // "my-app/dev/api/api-worker"
});
await app.finalize();
Using Scope Data Storage
const app = await alchemy("my-app");
// Store metadata
await app.set("deployedAt", Date.now());
await app.set("version", "1.0.0");
// Retrieve metadata
const deployedAt = await app.get<number>("deployedAt");
const version = await app.get<string>("version");
console.log(`Deployed v${version} at ${new Date(deployedAt)}`);
await app.finalize();
Deferred Operations
const app = await alchemy("my-app");
const worker = await Worker("api", {
entrypoint: "./src/worker.ts"
});
// Defer a warmup request until after deployment
const warmupResult = app.defer(async () => {
const response = await fetch(worker.url);
return response.status;
});
await app.finalize();
const status = await warmupResult;
console.log(`Warmup status: ${status}`);