import * as r2 from "@distilled.cloud/cloudflare/r2"; import * as Redacted from "effect/Redacted"; import * as Provider from "../../Provider.ts"; import { Resource } from "../../Resource.ts"; import { CloudflareEnvironment } from "../CloudflareEnvironment.ts"; import type { Providers } from "../Providers.ts"; import type { Bucket } from "./Bucket.ts"; declare const TypeId: "Cloudflare.R2.BucketSippy"; type TypeId = typeof TypeId; /** * Source bucket configuration for an AWS S3 origin. */ export interface BucketSippyAwsSource { /** Marks the source as an AWS S3 bucket. */ provider: "aws"; /** * Name of the AWS S3 bucket to migrate objects from. */ bucket: string; /** * AWS region the source bucket lives in, e.g. `us-east-1`. */ region: string; /** * Access Key ID of an AWS IAM credential with read access to the * source bucket. Write-only — Cloudflare never returns it. */ accessKeyId: Redacted.Redacted; /** * Secret Access Key paired with `accessKeyId`. Write-only. */ secretAccessKey: Redacted.Redacted; } /** * Source bucket configuration for a Google Cloud Storage origin. */ export interface BucketSippyGcsSource { /** Marks the source as a Google Cloud Storage bucket. */ provider: "gcs"; /** * Name of the GCS bucket to migrate objects from. */ bucket: string; /** * Client email of a GCP service account with read access to the * source bucket. */ clientEmail: string; /** * Private key of the GCP service account. Write-only — Cloudflare * never returns it. */ privateKey: Redacted.Redacted; } /** * The upstream bucket Sippy pulls objects from on R2 cache misses. */ export type BucketSippySource = BucketSippyAwsSource | BucketSippyGcsSource; /** * R2 credentials Sippy uses to write migrated objects into the * destination bucket. Create an R2 API token with write access to the * bucket and pass its S3-compatible credentials here. */ export interface BucketSippyDestination { /** * Access Key ID of the R2 API token. Write-only at the secret level — * Cloudflare echoes only the key ID back. */ accessKeyId: Redacted.Redacted; /** * Secret Access Key of the R2 API token. Write-only. */ secretAccessKey: Redacted.Redacted; } export interface BucketSippyProps { /** * Name of the R2 bucket to enable incremental migration into. Pass * `bucket.bucketName` from a `Cloudflare.R2.Bucket`. * * Immutable — changing the bucket triggers a replacement. */ bucketName: string; /** * Jurisdiction of the bucket (must match the bucket's own * jurisdiction). * * Immutable — changing the jurisdiction triggers a replacement. * @default "default" */ jurisdiction?: Bucket.Jurisdiction; /** * The upstream AWS S3 or Google Cloud Storage bucket to migrate * objects from. Source credentials are write-only — they are sent to * Cloudflare but never read back. */ source: BucketSippySource; /** * R2 API token credentials Sippy uses to write objects into the * destination bucket. */ destination: BucketSippyDestination; } export interface BucketSippyAttributes { /** Name of the R2 bucket Sippy is enabled on. */ bucketName: string; /** Account the bucket lives in. */ accountId: string; /** Jurisdiction of the bucket. */ jurisdiction: Bucket.Jurisdiction; /** Whether Sippy is currently enabled on the bucket. */ enabled: boolean; /** The configured source bucket as reported by Cloudflare (sans secrets). */ source: BucketSippy.SourceAttributes; /** The configured destination as reported by Cloudflare (sans secrets). */ destination: BucketSippy.DestinationAttributes; } export type BucketSippy = Resource; /** * Sippy — incremental migration from AWS S3 or Google Cloud Storage * into a Cloudflare R2 bucket. * * When Sippy is enabled on a bucket, any object requested from R2 that * is not yet present is fetched from the configured source bucket, * served, and copied into R2 — migrating data on demand without a bulk * transfer and without paying double storage during the transition. * * One Sippy configuration exists per bucket (it is a singleton * sub-resource of the bucket). Destroying the resource disables Sippy; * objects already migrated stay in the R2 bucket. * ### Migrating from AWS S3 * **Example:** Enable Sippy on a bucket with an S3 source * ```typescript * const bucket = yield* Cloudflare.R2.Bucket("Media"); * * yield* Cloudflare.R2.BucketSippy("MediaMigration", { * bucketName: bucket.bucketName, * source: { * provider: "aws", * bucket: "legacy-media", * region: "us-east-1", * accessKeyId: yield* Config.redacted("AWS_ACCESS_KEY_ID"), * secretAccessKey: yield* Config.redacted("AWS_SECRET_ACCESS_KEY"), * }, * destination: { * accessKeyId: yield* Config.redacted("R2_ACCESS_KEY_ID"), * secretAccessKey: yield* Config.redacted("R2_SECRET_ACCESS_KEY"), * }, * }); * ``` * * ### Migrating from Google Cloud Storage * **Example:** Enable Sippy with a GCS source * ```typescript * yield* Cloudflare.R2.BucketSippy("MediaMigration", { * bucketName: bucket.bucketName, * source: { * provider: "gcs", * bucket: "legacy-media", * clientEmail: "sippy@my-project.iam.gserviceaccount.com", * privateKey: yield* Config.redacted("GCS_PRIVATE_KEY"), * }, * destination: { * accessKeyId: yield* Config.redacted("R2_ACCESS_KEY_ID"), * secretAccessKey: yield* Config.redacted("R2_SECRET_ACCESS_KEY"), * }, * }); * ``` * * @see https://developers.cloudflare.com/r2/data-migration/sippy/ * * @resource * @product R2 * @category Storage & Databases */ export declare const BucketSippy: import("../../Resource.ts").ResourceClass; export declare namespace BucketSippy { /** * The source bucket as echoed back by Cloudflare. Secrets are never * returned. */ type SourceAttributes = { provider: "aws" | "gcs" | undefined; bucket: string | undefined; region: string | undefined; bucketUrl: string | undefined; }; /** * The destination as echoed back by Cloudflare. Only the access key * ID is returned, never the secret. */ type DestinationAttributes = { provider: "r2" | (string & {}) | undefined; account: string | undefined; bucket: string | undefined; accessKeyId: string | undefined; }; } /** * Returns true if the given value is an BucketSippy resource. */ export declare const isBucketSippy: (value: unknown) => value is BucketSippy; export declare const BucketSippyProvider: () => import("effect/Layer").Layer, never, CloudflareEnvironment | r2.CloudflareOpContext>; export {}; //# sourceMappingURL=BucketSippy.d.ts.map