Handle large result sets and asynchronous operations with built-in pagination and waiter utilities.
CloudFormation pagination utilities provide efficient handling of large result sets through automatic token management and streaming interfaces.
/**
* Base paginator configuration for CloudFormation operations
* Provides consistent pagination behavior across all commands
*/
interface PaginationConfiguration {
/** CloudFormation client instance */
client: CloudFormationClient;
/** Maximum number of items per page (command-specific limits apply) */
pageSize?: number;
/** Starting token for pagination continuation */
startingToken?: string;
}
/**
* Generic paginator result interface
* Provides async iteration over paginated results
*/
interface Paginator<T> {
[Symbol.asyncIterator](): AsyncIterator<T>;
}Paginates through stack listings with filtering support.
/**
* Paginates through stack listings with automatic token management
* Handles filtering and large result sets efficiently
*/
class ListStacksPaginator implements Paginator<ListStacksCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStacksCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStacksCommandOutput>;
}
interface ListStacksCommandInput {
/** Token for pagination continuation */
NextToken?: string;
/** Filter by stack status */
StackStatusFilter?: StackStatus[];
}Usage Examples:
import {
CloudFormationClient,
ListStacksPaginator,
StackStatus
} from "@aws-sdk/client-cloudformation";
const client = new CloudFormationClient({ region: "us-east-1" });
// Paginate through all stacks
const paginator = new ListStacksPaginator(
{
client,
pageSize: 50
},
{
StackStatusFilter: [
"CREATE_COMPLETE",
"UPDATE_COMPLETE",
"DELETE_COMPLETE"
]
}
);
// Iterate through all pages
const allStacks = [];
for await (const page of paginator) {
if (page.StackSummaries) {
allStacks.push(...page.StackSummaries);
console.log(`Retrieved ${page.StackSummaries.length} stacks in this page`);
}
}
console.log(`Total stacks found: ${allStacks.length}`);
// Process stacks as they arrive
for await (const page of paginator) {
if (page.StackSummaries) {
for (const stack of page.StackSummaries) {
console.log(`Stack: ${stack.StackName} - Status: ${stack.StackStatus}`);
// Process each stack immediately without storing all in memory
}
}
}Paginates through detailed stack information.
/**
* Paginates through detailed stack descriptions
* Supports filtering by stack name or status
*/
class DescribeStacksPaginator implements Paginator<DescribeStacksCommandOutput> {
constructor(
config: PaginationConfiguration,
input: DescribeStacksCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<DescribeStacksCommandOutput>;
}
interface DescribeStacksCommandInput {
/** Specific stack name or ARN (optional) */
StackName?: string;
/** Pagination token */
NextToken?: string;
}Paginates through stack resources with detailed information.
/**
* Paginates through stack resource listings
* Provides detailed resource information for large stacks
*/
class ListStackResourcesPaginator implements Paginator<ListStackResourcesCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStackResourcesCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStackResourcesCommandOutput>;
}
interface ListStackResourcesCommandInput {
/** Stack name or ARN */
StackName: string;
/** Pagination token */
NextToken?: string;
}Paginates through stack events and operational history.
/**
* Paginates through stack event history
* Provides chronological access to stack operations
*/
class DescribeStackEventsPaginator implements Paginator<DescribeStackEventsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: DescribeStackEventsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<DescribeStackEventsCommandOutput>;
}
interface DescribeStackEventsCommandInput {
/** Stack name or ARN (optional for all stacks) */
StackName?: string;
/** Pagination token */
NextToken?: string;
}Paginates through change sets for a stack.
/**
* Paginates through change sets for stack updates
* Lists all change sets associated with a stack
*/
class ListChangeSetsPaginator implements Paginator<ListChangeSetsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListChangeSetsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListChangeSetsCommandOutput>;
}
interface ListChangeSetsCommandInput {
/** Stack name or ARN */
StackName: string;
/** Pagination token */
NextToken?: string;
}Paginates through stack sets and their instances.
/**
* Paginates through stack sets in the account
* Supports filtering by status and call context
*/
class ListStackSetsPaginator implements Paginator<ListStackSetsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStackSetsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStackSetsCommandOutput>;
}
/**
* Paginates through stack instances in a stack set
* Supports filtering by account, region, and status
*/
class ListStackInstancesPaginator implements Paginator<ListStackInstancesCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStackInstancesCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStackInstancesCommandOutput>;
}
/**
* Paginates through stack set operations
* Shows history of stack set management operations
*/
class ListStackSetOperationsPaginator implements Paginator<ListStackSetOperationsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStackSetOperationsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStackSetOperationsCommandOutput>;
}Usage Examples:
// Monitor stack events in real-time
async function monitorStackEvents(stackName: string) {
const eventsPaginator = new DescribeStackEventsPaginator(
{ client, pageSize: 100 },
{ StackName: stackName }
);
for await (const page of eventsPaginator) {
if (page.StackEvents) {
// Process events in reverse chronological order (most recent first)
page.StackEvents.forEach(event => {
console.log(`${event.Timestamp}: ${event.LogicalResourceId} - ${event.ResourceStatus}`);
if (event.ResourceStatusReason) {
console.log(` Reason: ${event.ResourceStatusReason}`);
}
});
}
}
}
// Analyze resources across multiple stacks
async function analyzeStackResources() {
const stacksPaginator = new ListStacksPaginator(
{ client },
{ StackStatusFilter: ["CREATE_COMPLETE", "UPDATE_COMPLETE"] }
);
const resourceCounts = new Map<string, number>();
for await (const stacksPage of stacksPaginator) {
if (stacksPage.StackSummaries) {
for (const stack of stacksPage.StackSummaries) {
const resourcesPaginator = new ListStackResourcesPaginator(
{ client },
{ StackName: stack.StackName! }
);
for await (const resourcesPage of resourcesPaginator) {
if (resourcesPage.StackResourceSummaries) {
resourcesPage.StackResourceSummaries.forEach(resource => {
const count = resourceCounts.get(resource.ResourceType!) || 0;
resourceCounts.set(resource.ResourceType!, count + 1);
});
}
}
}
}
}
console.log("Resource type usage across all stacks:");
resourceCounts.forEach((count, type) => {
console.log(`${type}: ${count}`);
});
}/**
* Paginates through registered types
* Supports filtering by visibility, type, and other criteria
*/
class ListTypesPaginator implements Paginator<ListTypesCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListTypesCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListTypesCommandOutput>;
}
/**
* Paginates through versions of a specific type
* Shows version history and status information
*/
class ListTypeVersionsPaginator implements Paginator<ListTypeVersionsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListTypeVersionsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListTypeVersionsCommandOutput>;
}
/**
* Paginates through type registration operations
* Shows registration history and status
*/
class ListTypeRegistrationsPaginator implements Paginator<ListTypeRegistrationsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListTypeRegistrationsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListTypeRegistrationsCommandOutput>;
}/**
* Paginates through CloudFormation exports
* Lists all cross-stack exports in the region
*/
class ListExportsPaginator implements Paginator<ListExportsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListExportsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListExportsCommandOutput>;
}
/**
* Paginates through stack import operations
* Shows history of resource import operations
*/
class ListImportsPaginator implements Paginator<ListImportsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListImportsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListImportsCommandOutput>;
}/**
* Paginates through generated templates
* Lists all generated templates in the region
*/
class ListGeneratedTemplatesPaginator implements Paginator<ListGeneratedTemplatesCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListGeneratedTemplatesCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListGeneratedTemplatesCommandOutput>;
}/**
* Paginates through stack refactor operations
* Lists all refactor operations in the region
*/
class ListStackRefactorsPaginator implements Paginator<ListStackRefactorsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStackRefactorsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStackRefactorsCommandOutput>;
}
/**
* Paginates through actions in a stack refactor
* Shows detailed steps in refactor execution
*/
class ListStackRefactorActionsPaginator implements Paginator<ListStackRefactorActionsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListStackRefactorActionsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListStackRefactorActionsCommandOutput>;
}/**
* Paginates through resource scans
* Lists infrastructure scanning operations
*/
class ListResourceScansPaginator implements Paginator<ListResourceScansCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListResourceScansCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListResourceScansCommandOutput>;
}
/**
* Paginates through resources found in a scan
* Shows detailed resource discovery results
*/
class ListResourceScanResourcesPaginator implements Paginator<ListResourceScanResourcesCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListResourceScanResourcesCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListResourceScanResourcesCommandOutput>;
}
/**
* Paginates through related resources in a scan
* Shows resource relationships and dependencies
*/
class ListResourceScanRelatedResourcesPaginator implements Paginator<ListResourceScanRelatedResourcesCommandOutput> {
constructor(
config: PaginationConfiguration,
input: ListResourceScanRelatedResourcesCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<ListResourceScanRelatedResourcesCommandOutput>;
}/**
* Paginates through account limits
* Shows CloudFormation service limits and usage
*/
class DescribeAccountLimitsPaginator implements Paginator<DescribeAccountLimitsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: DescribeAccountLimitsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<DescribeAccountLimitsCommandOutput>;
}
/**
* Paginates through stack resource drift information
* Shows detailed drift analysis for resources
*/
class DescribeStackResourceDriftsPaginator implements Paginator<DescribeStackResourceDriftsCommandOutput> {
constructor(
config: PaginationConfiguration,
input: DescribeStackResourceDriftsCommandInput
);
async *[Symbol.asyncIterator](): AsyncIterator<DescribeStackResourceDriftsCommandOutput>;
}CloudFormation waiters provide polling mechanisms for asynchronous operations, automatically handling retries and timeouts.
/**
* Base configuration for CloudFormation waiters
* Controls polling behavior and timeout settings
*/
interface WaiterConfiguration<ClientType = CloudFormationClient> {
/** CloudFormation client instance */
client: ClientType;
/** Maximum time to wait in seconds (default: varies by waiter) */
maxWaitTime?: number;
/** Minimum delay between checks in seconds (default: varies by waiter) */
minDelay?: number;
/** Maximum delay between checks in seconds (default: varies by waiter) */
maxDelay?: number;
}
/**
* Result of a waiter operation
* Indicates success, failure, or timeout
*/
interface WaiterResult {
/** Final state of the waiter */
state: WaiterState;
/** Reason for the final state */
reason?: any;
}
type WaiterState =
| "SUCCESS"
| "FAILURE"
| "RETRY"
| "TIMEOUT"
| "ABORTED";/**
* Waits for stack creation to complete successfully
* Polls until stack reaches CREATE_COMPLETE or fails
*/
function waitForStackCreateComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStacksCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack update to complete successfully
* Polls until stack reaches UPDATE_COMPLETE or fails
*/
function waitForStackUpdateComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStacksCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack deletion to complete
* Polls until stack no longer exists or fails to delete
*/
function waitForStackDeleteComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStacksCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack rollback to complete
* Polls until rollback reaches final state
*/
function waitForStackRollbackComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStacksCommandInput
): Promise<WaiterResult>;
/**
* Waits for a stack to exist
* Useful when waiting for stack creation to begin
*/
function waitForStackExists(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStacksCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack import operation to complete
* Polls during import resource operations
*/
function waitForStackImportComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStacksCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack refactor creation to complete
* Polls during stack refactor preparation phase
*/
function waitForStackRefactorCreateComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStackRefactorCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack refactor execution to complete
* Polls during actual resource movement operations
*/
function waitForStackRefactorExecuteComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStackRefactorCommandInput
): Promise<WaiterResult>;/**
* Waits for change set creation to complete
* Polls until change set is ready for execution or fails
*/
function waitForChangeSetCreateComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeChangeSetCommandInput
): Promise<WaiterResult>;/**
* Waits for type registration to complete
* Polls during custom resource type registration
*/
function waitForTypeRegistrationComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeTypeRegistrationCommandInput
): Promise<WaiterResult>;Usage Examples:
import {
CloudFormationClient,
CreateStackCommand,
UpdateStackCommand,
DeleteStackCommand,
waitForStackCreateComplete,
waitForStackUpdateComplete,
waitForStackDeleteComplete,
WaiterResult
} from "@aws-sdk/client-cloudformation";
const client = new CloudFormationClient({ region: "us-east-1" });
// Create stack and wait for completion
async function createStackAndWait(stackName: string, templateBody: string) {
console.log(`Creating stack: ${stackName}`);
const createCommand = new CreateStackCommand({
StackName: stackName,
TemplateBody: templateBody,
Capabilities: ["CAPABILITY_IAM"]
});
await client.send(createCommand);
// Wait for creation to complete (default timeout: 120 minutes)
console.log("Waiting for stack creation to complete...");
const result = await waitForStackCreateComplete(
{
client,
maxWaitTime: 3600, // 1 hour timeout
minDelay: 15, // Check every 15 seconds minimum
maxDelay: 60 // Maximum 60 seconds between checks
},
{ StackName: stackName }
);
if (result.state === "SUCCESS") {
console.log(`Stack ${stackName} created successfully`);
return true;
} else {
console.error(`Stack creation failed: ${result.reason}`);
return false;
}
}
// Update stack with rollback handling
async function updateStackSafely(stackName: string, templateBody: string) {
try {
const updateCommand = new UpdateStackCommand({
StackName: stackName,
TemplateBody: templateBody,
Capabilities: ["CAPABILITY_IAM"]
});
await client.send(updateCommand);
console.log("Waiting for stack update to complete...");
const result = await waitForStackUpdateComplete(
{
client,
maxWaitTime: 2400 // 40 minutes
},
{ StackName: stackName }
);
if (result.state === "SUCCESS") {
console.log("Stack update completed successfully");
return true;
} else {
console.log("Stack update failed, waiting for rollback...");
const rollbackResult = await waitForStackRollbackComplete(
{ client },
{ StackName: stackName }
);
if (rollbackResult.state === "SUCCESS") {
console.log("Stack rollback completed");
}
return false;
}
} catch (error) {
console.error("Update failed:", error);
return false;
}
}
// Delete stack with verification
async function deleteStackCompletely(stackName: string) {
const deleteCommand = new DeleteStackCommand({
StackName: stackName
});
await client.send(deleteCommand);
console.log(`Waiting for stack ${stackName} to be deleted...`);
const result = await waitForStackDeleteComplete(
{
client,
maxWaitTime: 1800 // 30 minutes
},
{ StackName: stackName }
);
return result.state === "SUCCESS";
}/**
* Waits for change set creation to complete
* Polls until change set is available for review
*/
function waitForChangeSetCreateComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeChangeSetCommandInput
): Promise<WaiterResult>;/**
* Waits for type registration to complete
* Polls registration status until success or failure
*/
function waitForTypeRegistrationComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeTypeRegistrationCommandInput
): Promise<WaiterResult>;/**
* Waits for stack refactor creation to complete
* Used with CloudFormation refactoring operations
*/
function waitForStackRefactorCreateComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStackRefactorCommandInput
): Promise<WaiterResult>;
/**
* Waits for stack refactor execution to complete
* Monitors refactor operation progress
*/
function waitForStackRefactorExecuteComplete(
params: WaiterConfiguration<CloudFormationClient>,
input: DescribeStackRefactorCommandInput
): Promise<WaiterResult>;Advanced Usage Examples:
// Parallel stack operations with waiters
async function deployMultipleStacks(stackConfigs: Array<{name: string, template: string}>) {
const operations = stackConfigs.map(async (config) => {
try {
// Create stack
await client.send(new CreateStackCommand({
StackName: config.name,
TemplateBody: config.template,
Capabilities: ["CAPABILITY_IAM"]
}));
// Wait for completion
const result = await waitForStackCreateComplete(
{ client, maxWaitTime: 1800 },
{ StackName: config.name }
);
return {
stackName: config.name,
success: result.state === "SUCCESS",
error: result.state !== "SUCCESS" ? result.reason : null
};
} catch (error) {
return {
stackName: config.name,
success: false,
error: error
};
}
});
const results = await Promise.all(operations);
console.log("Deployment Results:");
results.forEach(result => {
console.log(`${result.stackName}: ${result.success ? 'SUCCESS' : 'FAILED'}`);
if (!result.success && result.error) {
console.log(` Error: ${result.error}`);
}
});
return results;
}
// Custom waiter with progress tracking
async function waitWithProgress<T>(
waiterFn: Promise<WaiterResult>,
progressCallback: (elapsed: number) => void
): Promise<WaiterResult> {
const startTime = Date.now();
let progressInterval: NodeJS.Timeout;
// Update progress every 30 seconds
progressInterval = setInterval(() => {
const elapsed = Math.floor((Date.now() - startTime) / 1000);
progressCallback(elapsed);
}, 30000);
try {
const result = await waiterFn;
clearInterval(progressInterval);
const totalTime = Math.floor((Date.now() - startTime) / 1000);
progressCallback(totalTime);
return result;
} catch (error) {
clearInterval(progressInterval);
throw error;
}
}
// Usage with progress tracking
const result = await waitWithProgress(
waitForStackCreateComplete(
{ client },
{ StackName: "my-large-stack" }
),
(elapsed) => {
console.log(`Stack creation in progress... ${elapsed} seconds elapsed`);
}
);/**
* Collects all items from a paginator into a single array
* Useful for small result sets that fit in memory
*/
async function collectPaginatorResults<T>(
paginator: Paginator<T>
): Promise<T[]> {
const results: T[] = [];
for await (const page of paginator) {
results.push(page);
}
return results;
}
/**
* Processes paginated results with a callback function
* Memory efficient for large result sets
*/
async function processPaginatedResults<T>(
paginator: Paginator<T>,
processor: (page: T) => Promise<void> | void
): Promise<void> {
for await (const page of paginator) {
await processor(page);
}
}