import type { Credentials } from "@distilled.cloud/aws/Credentials"; import type { Region } from "@distilled.cloud/aws/Region"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import type { HttpClient } from "effect/unstable/http/HttpClient"; import { State, type StateService } from "../../State/State.ts"; import { AWSEnvironment } from "../Environment.ts"; import type { BucketEncryption } from "../S3/Bucket.ts"; export interface S3StateOptions { /** * Name of the S3 bucket that holds the state objects. The bucket is * created on first use if it does not exist. * * The bucket is created in the account-regional namespace, so custom * names must follow the `---an` convention. * * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/gpbucketnamespaces.html#account-regional-gp-buckets * @default `alchemy-state-{accountId}-{region}-an` */ bucketName?: string; /** * Key prefix within the bucket under which all state objects are * stored, e.g. `"alchemy"`. A trailing `/` is appended automatically. * * @default "" (bucket root) */ prefix?: string; /** * Default encryption enforced on the state bucket. * * @default `{ sseAlgorithm: "AES256" }` */ encryption?: BucketEncryption; } /** Context required by the distilled S3 operations. */ type S3Deps = Credentials | HttpClient | Region; /** * State store backed by an AWS S3 bucket. * * Stack state is persisted as JSON objects in an account-regional S3 * bucket, laid out exactly like the local state store's file tree with * the bucket (plus optional `prefix`) taking the place of the * `.alchemy/state` directory: * * ``` * s3://{bucket}/{prefix}{stack}/{stage}/{fqn}.json * s3://{bucket}/{prefix}{stack}/{stage}/__stack_output__.json * ``` * * The bucket is created lazily on the first state operation if it does * not already exist — nothing touches AWS credentials at layer * construction time. * * * ### Using the S3 State Store * Pass `AWS.state()` as the `state` option of a Stack. By default the * state is stored in an account-regional bucket named * `alchemy-state-{accountId}-{region}-an`. * * **Example:** Default bucket * ```typescript * import * as Alchemy from "alchemy"; * import * as AWS from "alchemy/AWS"; * * const Stack = Alchemy.Stack( * "my-stack", * { providers: AWS.providers(), state: AWS.state() }, * Effect.gen(function* () { * // ... * }), * ); * ``` * * **Example:** Custom bucket and key prefix * ```typescript * const Stack = Alchemy.Stack( * "my-stack", * { * providers: AWS.providers(), * state: AWS.state({ * bucketName: "my-company-state", * prefix: "alchemy", * encryption: { * sseAlgorithm: "aws:kms", * kmsMasterKeyId: "alias/alchemy-state", * }, * }), * }, * Effect.gen(function* () { * // ... * }), * ); * ``` * * @resource */ export declare const state: (options?: S3StateOptions) => Layer.Layer; /** * Construct an S3-backed {@link StateService}. * * Construction itself never touches AWS — environment resolution and * the ensure-bucket-exists check are deferred into a cached Effect * that runs once, on the first state operation. */ export declare const makeS3State: (options?: S3StateOptions) => Effect.Effect; /** * Build the default account-regional state bucket name. * * Account-regional buckets must follow the naming convention: * `---an` * * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/gpbucketnamespaces.html#account-regional-gp-buckets */ export declare const createStateBucketName: (accountId: string, region: string) => string; export {}; //# sourceMappingURL=State.d.ts.map