Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/pulumi/api.md
1# API & Data Sources23## Outputs and Exports45Export resource identifiers:67```typescript8export const kvId = kv.id;9export const bucketName = bucket.name;10export const workerUrl = worker.subdomain;11export const dbId = db.id;12```1314## Resource Dependencies1516Implicit dependencies via outputs:1718```typescript19const kv = new cloudflare.WorkersKvNamespace("kv", {20accountId: accountId,21title: "my-kv",22});2324// Worker depends on KV (implicit via kv.id)25const worker = new cloudflare.WorkerScript("worker", {26accountId: accountId,27name: "my-worker",28content: code,29kvNamespaceBindings: [{name: "MY_KV", namespaceId: kv.id}], // Creates dependency30});31```3233Explicit dependencies:3435```typescript36const migration = new command.local.Command("migration", {37create: pulumi.interpolate`wrangler d1 execute ${db.name} --file ./schema.sql`,38}, {dependsOn: [db]});3940const worker = new cloudflare.WorkerScript("worker", {41accountId: accountId,42name: "worker",43content: code,44d1DatabaseBindings: [{name: "DB", databaseId: db.id}],45}, {dependsOn: [migration]}); // Ensure migrations run first46```4748## Using Outputs with API Calls4950```typescript51const db = new cloudflare.D1Database("db", {accountId, name: "my-db"});5253db.id.apply(async (dbId) => {54const response = await fetch(55`https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${dbId}/query`,56{method: "POST", headers: {"Authorization": `Bearer ${apiToken}`, "Content-Type": "application/json"},57body: JSON.stringify({sql: "CREATE TABLE users (id INT)"})}58);59return response.json();60});61```6263## Custom Dynamic Providers6465For resources not in provider:6667```typescript68import * as pulumi from "@pulumi/pulumi";6970class D1MigrationProvider implements pulumi.dynamic.ResourceProvider {71async create(inputs: any): Promise<pulumi.dynamic.CreateResult> {72const response = await fetch(73`https://api.cloudflare.com/client/v4/accounts/${inputs.accountId}/d1/database/${inputs.databaseId}/query`,74{method: "POST", headers: {"Authorization": `Bearer ${inputs.apiToken}`, "Content-Type": "application/json"},75body: JSON.stringify({sql: inputs.sql})}76);77return {id: `${inputs.databaseId}-${Date.now()}`, outs: await response.json()};78}79async update(id: string, olds: any, news: any): Promise<pulumi.dynamic.UpdateResult> {80if (olds.sql !== news.sql) await this.create(news);81return {};82}83async delete(id: string, props: any): Promise<void> {}84}8586class D1Migration extends pulumi.dynamic.Resource {87constructor(name: string, args: any, opts?: pulumi.CustomResourceOptions) {88super(new D1MigrationProvider(), name, args, opts);89}90}9192const migration = new D1Migration("migration", {93accountId, databaseId: db.id, apiToken, sql: "CREATE TABLE users (id INT)",94}, {dependsOn: [db]});95```9697## Data Sources9899**Get Zone:**100```typescript101const zone = cloudflare.getZone({name: "example.com"});102const zoneId = zone.then(z => z.id);103```104105**Get Accounts (via API):**106Use Cloudflare API directly or custom dynamic resources.107108## Import Existing Resources109110```bash111# Import worker112pulumi import cloudflare:index/workerScript:WorkerScript my-worker <account_id>/<worker_name>113114# Import KV namespace115pulumi import cloudflare:index/workersKvNamespace:WorkersKvNamespace my-kv <namespace_id>116117# Import R2 bucket118pulumi import cloudflare:index/r2Bucket:R2Bucket my-bucket <account_id>/<bucket_name>119120# Import D1 database121pulumi import cloudflare:index/d1Database:D1Database my-db <account_id>/<database_id>122123# Import DNS record124pulumi import cloudflare:index/dnsRecord:DnsRecord my-record <zone_id>/<record_id>125```126127## Secrets Management128129```typescript130import * as pulumi from "@pulumi/pulumi";131132const config = new pulumi.Config();133const apiKey = config.requireSecret("apiKey"); // Encrypted in state134135const worker = new cloudflare.WorkerScript("worker", {136accountId: accountId,137name: "my-worker",138content: code,139secretTextBindings: [{name: "API_KEY", text: apiKey}],140});141```142143Store secrets:144```bash145pulumi config set --secret apiKey "secret-value"146```147148## Transform Pattern149150Modify resource args before creation:151152```typescript153import {Transform} from "@pulumi/pulumi";154155interface BucketArgs {156accountId: pulumi.Input<string>;157transform?: {bucket?: Transform<cloudflare.R2BucketArgs>};158}159160function createBucket(name: string, args: BucketArgs) {161const bucketArgs: cloudflare.R2BucketArgs = {162accountId: args.accountId,163name: name,164location: "auto",165};166const finalArgs = args.transform?.bucket?.(bucketArgs) ?? bucketArgs;167return new cloudflare.R2Bucket(name, finalArgs);168}169```170171## v6.x Worker Versioning Resources172173**Worker** - Container for versions:174```typescript175const worker = new cloudflare.Worker("api", {accountId, name: "api-worker"});176export const workerId = worker.id;177```178179**WorkerVersion** - Immutable code + config:180```typescript181const version = new cloudflare.WorkerVersion("v1", {182accountId, workerId: worker.id,183content: fs.readFileSync("./dist/worker.js", "utf8"),184compatibilityDate: "2025-01-01",185});186export const versionId = version.id;187```188189**WorkersDeployment** - Active deployment with bindings:190```typescript191const deployment = new cloudflare.WorkersDeployment("prod", {192accountId, workerId: worker.id, versionId: version.id,193kvNamespaceBindings: [{name: "MY_KV", namespaceId: kv.id}],194});195```196197**Use:** Advanced deployments (canary, blue-green). Most apps should use `WorkerScript` (auto-versioning).198199---200See: [README.md](./README.md), [configuration.md](./configuration.md), [patterns.md](./patterns.md), [gotchas.md](./gotchas.md)201