Skip to content

Make Cloudflare bindings extensible - #6954

Open
c-w-xiaohei wants to merge 2 commits into
anomalyco:devfrom
c-w-xiaohei:refactor/cloudflare-extandable
Open

Make Cloudflare bindings extensible#6954
c-w-xiaohei wants to merge 2 commits into
anomalyco:devfrom
c-w-xiaohei:refactor/cloudflare-extandable

Conversation

@c-w-xiaohei

@c-w-xiaohei c-w-xiaohei commented Jul 25, 2026

Copy link
Copy Markdown

Summary

Closes #6941.

This removes SST's closed, centrally maintained Cloudflare binding model and lets each Cloudflare resource declare its production binding, Wrangler development configuration, and runtime TypeScript type independently.

The production binding helper now accepts the provider-shaped WorkersScriptBinding input directly. SST adds the final binding name but otherwise leaves provider fields untouched, allowing bindings supported by the Cloudflare provider to be used without first adding another SST binding-kind mapping.

Existing SST binding inputs remain supported and are normalized to the provider shape, so current applications do not need to migrate immediately.

What changed

  • Add a CloudflareComponent base class that assembles the production Worker binding, Wrangler development configuration, and runtime TypeScript type.
  • Change sst.cloudflare.binding() to accept provider-shaped Worker binding inputs.
  • Preserve compatibility with the existing SST binding names and nested properties shape.
  • Make the Worker production path consume bindings generically instead of mapping known binding kinds.
  • Make Go typegen consume an explicit typescript.type include instead of deriving types from Cloudflare binding names.
  • Add link-scoped Wrangler configuration composition with placeholder replacement, ownership tracking, duplicate detection, and conflict errors.
  • Migrate the existing first-party Cloudflare components to declare their own production, development, and runtime type projections.
  • Pin Wrangler so the development configuration type and generated behavior use the same schema version.

Compatibility

Existing inputs continue to work:

sst.cloudflare.binding({
  type: "r2BucketBindings",
  properties: {
    bucketName: bucket.name,
  },
});

They are normalized to the provider shape:

{
  type: "r2_bucket",
  bucketName: bucket.name,
}

New code can use the provider shape directly:

sst.cloudflare.binding({
  type: "r2_bucket",
  bucketName: bucket.name,
});

Both forms produce the same production Worker binding after SST assigns the final link name.

Extension example

A custom Cloudflare component can now provide all three projections without adding an SST union member, Worker switch, Wrangler mapping, or Go type mapping:

class Search extends sst.cloudflare.CloudflareComponent {
  protected readonly binding: sst.cloudflare.CloudflareBinding;
  protected readonly type =
    `import("@cloudflare/workers-types").AiSearchInstance`;

  private readonly instanceName: $util.Input<string>;

  constructor(
    name: string,
    args: { instanceName: $util.Input<string> },
    opts?: $util.ComponentResourceOptions,
  ) {
    super("example:cloudflare:Search", name, args, opts);

    this.instanceName = args.instanceName;
    this.binding = {
      type: "ai_search",
      instanceName: this.instanceName,
    };
    this.devConfig = {
      ai_search: [{
        binding: this.linkNamePlaceholder,
        instance_name: this.instanceName,
        remote: true,
      }],
    };
  }

  protected getLinkDefinition() {
    return {
      properties: {
        instanceName: this.instanceName,
      },
    };
  }
}

Design boundaries

  • cloudflare.binding describes only the production Worker binding.
  • cloudflare.dev is consumed only by the Wrangler development path.
  • typescript.type is consumed only by typegen.
  • Queue consumers remain relationships rather than link-scoped bindings.
  • Worker-scoped configuration such as migrations, routes, schedules, and assets is not inferred from linked resources.
  • The Cloudflare provider and API remain responsible for validating provider binding kinds and fields.
  • This does not add a registry or change Link.Definition.

Verification

Passed:

  • bunx vitest run test/components/cloudflare (94 tests)
  • bunx tsc --noEmit --pretty false
  • bun run build:platform

@c-w-xiaohei
c-w-xiaohei force-pushed the refactor/cloudflare-extandable branch from 4ad82f2 to 939d0b4 Compare July 27, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFC: Extensible Cloudflare Bindings, Development Configuration, and Runtime Types

1 participant