pi-cloudflare 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +67 -0
- package/bin/setup.mjs +103 -0
- package/dist/auth-flow.d.ts +15 -0
- package/dist/auth-flow.d.ts.map +1 -0
- package/dist/auth-flow.js +90 -0
- package/dist/auth-flow.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +47 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +44 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +135 -0
- package/dist/oauth.js.map +1 -0
- package/dist/proxy.d.ts +29 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +39 -0
- package/dist/proxy.js.map +1 -0
- package/dist/servers.d.ts +19 -0
- package/dist/servers.d.ts.map +1 -0
- package/dist/servers.js +40 -0
- package/dist/servers.js.map +1 -0
- package/dist/token-store.d.ts +23 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +47 -0
- package/dist/token-store.js.map +1 -0
- package/package.json +67 -0
- package/skills/agents-sdk/SKILL.md +221 -0
- package/skills/agents-sdk/references/browse-the-web.md +63 -0
- package/skills/agents-sdk/references/callable.md +92 -0
- package/skills/agents-sdk/references/client-sdk.md +110 -0
- package/skills/agents-sdk/references/codemode.md +110 -0
- package/skills/agents-sdk/references/configuration.md +72 -0
- package/skills/agents-sdk/references/durable-execution.md +51 -0
- package/skills/agents-sdk/references/email.md +146 -0
- package/skills/agents-sdk/references/human-in-the-loop.md +67 -0
- package/skills/agents-sdk/references/mcp.md +188 -0
- package/skills/agents-sdk/references/observability.md +44 -0
- package/skills/agents-sdk/references/queue-retries.md +79 -0
- package/skills/agents-sdk/references/routing.md +75 -0
- package/skills/agents-sdk/references/server-driven-messages.md +63 -0
- package/skills/agents-sdk/references/state-scheduling.md +171 -0
- package/skills/agents-sdk/references/streaming-chat.md +198 -0
- package/skills/agents-sdk/references/think.md +112 -0
- package/skills/agents-sdk/references/voice.md +68 -0
- package/skills/agents-sdk/references/webhooks-push.md +86 -0
- package/skills/agents-sdk/references/workflows.md +132 -0
- package/skills/cloudflare/SKILL.md +248 -0
- package/skills/cloudflare/references/agents-sdk/README.md +89 -0
- package/skills/cloudflare/references/agents-sdk/api.md +190 -0
- package/skills/cloudflare/references/agents-sdk/configuration.md +182 -0
- package/skills/cloudflare/references/agents-sdk/gotchas.md +158 -0
- package/skills/cloudflare/references/agents-sdk/patterns.md +192 -0
- package/skills/cloudflare/references/ai-gateway/README.md +175 -0
- package/skills/cloudflare/references/ai-gateway/configuration.md +111 -0
- package/skills/cloudflare/references/ai-gateway/dynamic-routing.md +82 -0
- package/skills/cloudflare/references/ai-gateway/features.md +96 -0
- package/skills/cloudflare/references/ai-gateway/sdk-integration.md +114 -0
- package/skills/cloudflare/references/ai-gateway/troubleshooting.md +88 -0
- package/skills/cloudflare/references/ai-search/README.md +138 -0
- package/skills/cloudflare/references/ai-search/api.md +87 -0
- package/skills/cloudflare/references/ai-search/configuration.md +88 -0
- package/skills/cloudflare/references/ai-search/gotchas.md +81 -0
- package/skills/cloudflare/references/ai-search/patterns.md +85 -0
- package/skills/cloudflare/references/analytics-engine/README.md +94 -0
- package/skills/cloudflare/references/analytics-engine/api.md +112 -0
- package/skills/cloudflare/references/analytics-engine/configuration.md +112 -0
- package/skills/cloudflare/references/analytics-engine/gotchas.md +85 -0
- package/skills/cloudflare/references/analytics-engine/patterns.md +83 -0
- package/skills/cloudflare/references/api/README.md +66 -0
- package/skills/cloudflare/references/api/api.md +204 -0
- package/skills/cloudflare/references/api/configuration.md +160 -0
- package/skills/cloudflare/references/api/gotchas.md +225 -0
- package/skills/cloudflare/references/api/patterns.md +204 -0
- package/skills/cloudflare/references/api-shield/README.md +44 -0
- package/skills/cloudflare/references/api-shield/api.md +141 -0
- package/skills/cloudflare/references/api-shield/configuration.md +192 -0
- package/skills/cloudflare/references/api-shield/gotchas.md +125 -0
- package/skills/cloudflare/references/api-shield/patterns.md +180 -0
- package/skills/cloudflare/references/argo-smart-routing/README.md +90 -0
- package/skills/cloudflare/references/argo-smart-routing/api.md +240 -0
- package/skills/cloudflare/references/argo-smart-routing/configuration.md +197 -0
- package/skills/cloudflare/references/argo-smart-routing/gotchas.md +111 -0
- package/skills/cloudflare/references/argo-smart-routing/patterns.md +104 -0
- package/skills/cloudflare/references/artifacts/README.md +79 -0
- package/skills/cloudflare/references/artifacts/api.md +128 -0
- package/skills/cloudflare/references/artifacts/configuration.md +92 -0
- package/skills/cloudflare/references/bindings/README.md +122 -0
- package/skills/cloudflare/references/bindings/api.md +203 -0
- package/skills/cloudflare/references/bindings/configuration.md +188 -0
- package/skills/cloudflare/references/bindings/gotchas.md +208 -0
- package/skills/cloudflare/references/bindings/patterns.md +200 -0
- package/skills/cloudflare/references/bot-management/README.md +94 -0
- package/skills/cloudflare/references/bot-management/api.md +169 -0
- package/skills/cloudflare/references/bot-management/configuration.md +163 -0
- package/skills/cloudflare/references/bot-management/gotchas.md +114 -0
- package/skills/cloudflare/references/bot-management/patterns.md +182 -0
- package/skills/cloudflare/references/browser-rendering/README.md +78 -0
- package/skills/cloudflare/references/browser-rendering/api.md +108 -0
- package/skills/cloudflare/references/browser-rendering/configuration.md +78 -0
- package/skills/cloudflare/references/browser-rendering/gotchas.md +88 -0
- package/skills/cloudflare/references/browser-rendering/patterns.md +91 -0
- package/skills/cloudflare/references/c3/README.md +111 -0
- package/skills/cloudflare/references/c3/api.md +71 -0
- package/skills/cloudflare/references/c3/configuration.md +81 -0
- package/skills/cloudflare/references/c3/gotchas.md +92 -0
- package/skills/cloudflare/references/c3/patterns.md +82 -0
- package/skills/cloudflare/references/cache-reserve/README.md +147 -0
- package/skills/cloudflare/references/cache-reserve/api.md +194 -0
- package/skills/cloudflare/references/cache-reserve/configuration.md +169 -0
- package/skills/cloudflare/references/cache-reserve/gotchas.md +132 -0
- package/skills/cloudflare/references/cache-reserve/patterns.md +197 -0
- package/skills/cloudflare/references/containers/README.md +85 -0
- package/skills/cloudflare/references/containers/api.md +187 -0
- package/skills/cloudflare/references/containers/configuration.md +188 -0
- package/skills/cloudflare/references/containers/gotchas.md +178 -0
- package/skills/cloudflare/references/containers/patterns.md +202 -0
- package/skills/cloudflare/references/cron-triggers/README.md +99 -0
- package/skills/cloudflare/references/cron-triggers/api.md +196 -0
- package/skills/cloudflare/references/cron-triggers/configuration.md +180 -0
- package/skills/cloudflare/references/cron-triggers/gotchas.md +199 -0
- package/skills/cloudflare/references/cron-triggers/patterns.md +190 -0
- package/skills/cloudflare/references/d1/README.md +133 -0
- package/skills/cloudflare/references/d1/api.md +196 -0
- package/skills/cloudflare/references/d1/configuration.md +191 -0
- package/skills/cloudflare/references/d1/gotchas.md +98 -0
- package/skills/cloudflare/references/d1/patterns.md +189 -0
- package/skills/cloudflare/references/ddos/README.md +41 -0
- package/skills/cloudflare/references/ddos/api.md +164 -0
- package/skills/cloudflare/references/ddos/configuration.md +93 -0
- package/skills/cloudflare/references/ddos/gotchas.md +107 -0
- package/skills/cloudflare/references/ddos/patterns.md +174 -0
- package/skills/cloudflare/references/do-storage/README.md +75 -0
- package/skills/cloudflare/references/do-storage/api.md +102 -0
- package/skills/cloudflare/references/do-storage/configuration.md +112 -0
- package/skills/cloudflare/references/do-storage/gotchas.md +150 -0
- package/skills/cloudflare/references/do-storage/patterns.md +194 -0
- package/skills/cloudflare/references/do-storage/testing.md +183 -0
- package/skills/cloudflare/references/durable-objects/README.md +185 -0
- package/skills/cloudflare/references/durable-objects/api.md +187 -0
- package/skills/cloudflare/references/durable-objects/configuration.md +160 -0
- package/skills/cloudflare/references/durable-objects/gotchas.md +197 -0
- package/skills/cloudflare/references/durable-objects/patterns.md +201 -0
- package/skills/cloudflare/references/email-routing/README.md +89 -0
- package/skills/cloudflare/references/email-routing/api.md +195 -0
- package/skills/cloudflare/references/email-routing/configuration.md +186 -0
- package/skills/cloudflare/references/email-routing/gotchas.md +196 -0
- package/skills/cloudflare/references/email-routing/patterns.md +229 -0
- package/skills/cloudflare/references/email-workers/README.md +151 -0
- package/skills/cloudflare/references/email-workers/api.md +237 -0
- package/skills/cloudflare/references/email-workers/configuration.md +112 -0
- package/skills/cloudflare/references/email-workers/gotchas.md +125 -0
- package/skills/cloudflare/references/email-workers/patterns.md +102 -0
- package/skills/cloudflare/references/flagship/README.md +59 -0
- package/skills/cloudflare/references/flagship/api.md +390 -0
- package/skills/cloudflare/references/flagship/configuration.md +202 -0
- package/skills/cloudflare/references/flagship/gotchas.md +178 -0
- package/skills/cloudflare/references/flagship/patterns.md +469 -0
- package/skills/cloudflare/references/graphql-api/README.md +147 -0
- package/skills/cloudflare/references/graphql-api/api.md +175 -0
- package/skills/cloudflare/references/graphql-api/configuration.md +118 -0
- package/skills/cloudflare/references/graphql-api/gotchas.md +110 -0
- package/skills/cloudflare/references/graphql-api/patterns.md +225 -0
- package/skills/cloudflare/references/hyperdrive/README.md +82 -0
- package/skills/cloudflare/references/hyperdrive/api.md +143 -0
- package/skills/cloudflare/references/hyperdrive/configuration.md +159 -0
- package/skills/cloudflare/references/hyperdrive/gotchas.md +77 -0
- package/skills/cloudflare/references/hyperdrive/patterns.md +190 -0
- package/skills/cloudflare/references/images/README.md +61 -0
- package/skills/cloudflare/references/images/api.md +96 -0
- package/skills/cloudflare/references/images/configuration.md +211 -0
- package/skills/cloudflare/references/images/gotchas.md +99 -0
- package/skills/cloudflare/references/images/patterns.md +115 -0
- package/skills/cloudflare/references/kv/README.md +89 -0
- package/skills/cloudflare/references/kv/api.md +160 -0
- package/skills/cloudflare/references/kv/configuration.md +144 -0
- package/skills/cloudflare/references/kv/gotchas.md +131 -0
- package/skills/cloudflare/references/kv/patterns.md +196 -0
- package/skills/cloudflare/references/miniflare/README.md +105 -0
- package/skills/cloudflare/references/miniflare/api.md +187 -0
- package/skills/cloudflare/references/miniflare/configuration.md +173 -0
- package/skills/cloudflare/references/miniflare/gotchas.md +160 -0
- package/skills/cloudflare/references/miniflare/patterns.md +181 -0
- package/skills/cloudflare/references/network-interconnect/README.md +99 -0
- package/skills/cloudflare/references/network-interconnect/api.md +199 -0
- package/skills/cloudflare/references/network-interconnect/configuration.md +114 -0
- package/skills/cloudflare/references/network-interconnect/gotchas.md +165 -0
- package/skills/cloudflare/references/network-interconnect/patterns.md +166 -0
- package/skills/cloudflare/references/observability/README.md +88 -0
- package/skills/cloudflare/references/observability/api.md +164 -0
- package/skills/cloudflare/references/observability/configuration.md +169 -0
- package/skills/cloudflare/references/observability/gotchas.md +115 -0
- package/skills/cloudflare/references/observability/patterns.md +105 -0
- package/skills/cloudflare/references/pages/README.md +88 -0
- package/skills/cloudflare/references/pages/api.md +204 -0
- package/skills/cloudflare/references/pages/configuration.md +201 -0
- package/skills/cloudflare/references/pages/gotchas.md +203 -0
- package/skills/cloudflare/references/pages/patterns.md +204 -0
- package/skills/cloudflare/references/pages-functions/README.md +98 -0
- package/skills/cloudflare/references/pages-functions/api.md +143 -0
- package/skills/cloudflare/references/pages-functions/configuration.md +122 -0
- package/skills/cloudflare/references/pages-functions/gotchas.md +94 -0
- package/skills/cloudflare/references/pages-functions/patterns.md +137 -0
- package/skills/cloudflare/references/pipelines/README.md +90 -0
- package/skills/cloudflare/references/pipelines/api.md +124 -0
- package/skills/cloudflare/references/pipelines/configuration.md +155 -0
- package/skills/cloudflare/references/pipelines/gotchas.md +58 -0
- package/skills/cloudflare/references/pipelines/patterns.md +130 -0
- package/skills/cloudflare/references/pulumi/README.md +100 -0
- package/skills/cloudflare/references/pulumi/api.md +200 -0
- package/skills/cloudflare/references/pulumi/configuration.md +198 -0
- package/skills/cloudflare/references/pulumi/gotchas.md +181 -0
- package/skills/cloudflare/references/pulumi/patterns.md +191 -0
- package/skills/cloudflare/references/queues/README.md +96 -0
- package/skills/cloudflare/references/queues/api.md +206 -0
- package/skills/cloudflare/references/queues/configuration.md +144 -0
- package/skills/cloudflare/references/queues/gotchas.md +206 -0
- package/skills/cloudflare/references/queues/patterns.md +220 -0
- package/skills/cloudflare/references/r2/README.md +95 -0
- package/skills/cloudflare/references/r2/api.md +200 -0
- package/skills/cloudflare/references/r2/configuration.md +165 -0
- package/skills/cloudflare/references/r2/gotchas.md +190 -0
- package/skills/cloudflare/references/r2/patterns.md +193 -0
- package/skills/cloudflare/references/r2-data-catalog/README.md +75 -0
- package/skills/cloudflare/references/r2-data-catalog/api.md +122 -0
- package/skills/cloudflare/references/r2-data-catalog/configuration.md +98 -0
- package/skills/cloudflare/references/r2-data-catalog/gotchas.md +55 -0
- package/skills/cloudflare/references/r2-data-catalog/patterns.md +122 -0
- package/skills/cloudflare/references/r2-sql/README.md +64 -0
- package/skills/cloudflare/references/r2-sql/api.md +121 -0
- package/skills/cloudflare/references/r2-sql/configuration.md +50 -0
- package/skills/cloudflare/references/r2-sql/gotchas.md +39 -0
- package/skills/cloudflare/references/r2-sql/patterns.md +118 -0
- package/skills/cloudflare/references/realtime-sfu/README.md +65 -0
- package/skills/cloudflare/references/realtime-sfu/api.md +158 -0
- package/skills/cloudflare/references/realtime-sfu/configuration.md +137 -0
- package/skills/cloudflare/references/realtime-sfu/gotchas.md +133 -0
- package/skills/cloudflare/references/realtime-sfu/patterns.md +174 -0
- package/skills/cloudflare/references/realtimekit/README.md +113 -0
- package/skills/cloudflare/references/realtimekit/api.md +212 -0
- package/skills/cloudflare/references/realtimekit/configuration.md +203 -0
- package/skills/cloudflare/references/realtimekit/gotchas.md +169 -0
- package/skills/cloudflare/references/realtimekit/patterns.md +223 -0
- package/skills/cloudflare/references/sandbox/README.md +96 -0
- package/skills/cloudflare/references/sandbox/api.md +198 -0
- package/skills/cloudflare/references/sandbox/configuration.md +143 -0
- package/skills/cloudflare/references/sandbox/gotchas.md +194 -0
- package/skills/cloudflare/references/sandbox/patterns.md +201 -0
- package/skills/cloudflare/references/secrets-store/README.md +74 -0
- package/skills/cloudflare/references/secrets-store/api.md +200 -0
- package/skills/cloudflare/references/secrets-store/configuration.md +185 -0
- package/skills/cloudflare/references/secrets-store/gotchas.md +97 -0
- package/skills/cloudflare/references/secrets-store/patterns.md +207 -0
- package/skills/cloudflare/references/smart-placement/README.md +138 -0
- package/skills/cloudflare/references/smart-placement/api.md +183 -0
- package/skills/cloudflare/references/smart-placement/configuration.md +196 -0
- package/skills/cloudflare/references/smart-placement/gotchas.md +174 -0
- package/skills/cloudflare/references/smart-placement/patterns.md +183 -0
- package/skills/cloudflare/references/snippets/README.md +68 -0
- package/skills/cloudflare/references/snippets/api.md +198 -0
- package/skills/cloudflare/references/snippets/configuration.md +227 -0
- package/skills/cloudflare/references/snippets/gotchas.md +86 -0
- package/skills/cloudflare/references/snippets/patterns.md +135 -0
- package/skills/cloudflare/references/spectrum/README.md +52 -0
- package/skills/cloudflare/references/spectrum/api.md +181 -0
- package/skills/cloudflare/references/spectrum/configuration.md +194 -0
- package/skills/cloudflare/references/spectrum/gotchas.md +145 -0
- package/skills/cloudflare/references/spectrum/patterns.md +196 -0
- package/skills/cloudflare/references/static-assets/README.md +65 -0
- package/skills/cloudflare/references/static-assets/api.md +199 -0
- package/skills/cloudflare/references/static-assets/configuration.md +186 -0
- package/skills/cloudflare/references/static-assets/gotchas.md +162 -0
- package/skills/cloudflare/references/static-assets/patterns.md +189 -0
- package/skills/cloudflare/references/stream/README.md +114 -0
- package/skills/cloudflare/references/stream/api-live.md +195 -0
- package/skills/cloudflare/references/stream/api.md +199 -0
- package/skills/cloudflare/references/stream/configuration.md +141 -0
- package/skills/cloudflare/references/stream/gotchas.md +130 -0
- package/skills/cloudflare/references/stream/patterns.md +184 -0
- package/skills/cloudflare/references/tail-workers/README.md +89 -0
- package/skills/cloudflare/references/tail-workers/api.md +200 -0
- package/skills/cloudflare/references/tail-workers/configuration.md +176 -0
- package/skills/cloudflare/references/tail-workers/gotchas.md +192 -0
- package/skills/cloudflare/references/tail-workers/patterns.md +180 -0
- package/skills/cloudflare/references/terraform/README.md +102 -0
- package/skills/cloudflare/references/terraform/api.md +178 -0
- package/skills/cloudflare/references/terraform/configuration.md +197 -0
- package/skills/cloudflare/references/terraform/gotchas.md +150 -0
- package/skills/cloudflare/references/terraform/patterns.md +174 -0
- package/skills/cloudflare/references/tunnel/README.md +129 -0
- package/skills/cloudflare/references/tunnel/api.md +193 -0
- package/skills/cloudflare/references/tunnel/configuration.md +157 -0
- package/skills/cloudflare/references/tunnel/gotchas.md +147 -0
- package/skills/cloudflare/references/tunnel/networking.md +168 -0
- package/skills/cloudflare/references/tunnel/patterns.md +192 -0
- package/skills/cloudflare/references/turn/README.md +82 -0
- package/skills/cloudflare/references/turn/api.md +239 -0
- package/skills/cloudflare/references/turn/configuration.md +179 -0
- package/skills/cloudflare/references/turn/gotchas.md +231 -0
- package/skills/cloudflare/references/turn/patterns.md +213 -0
- package/skills/cloudflare/references/turnstile/README.md +99 -0
- package/skills/cloudflare/references/turnstile/api.md +240 -0
- package/skills/cloudflare/references/turnstile/configuration.md +222 -0
- package/skills/cloudflare/references/turnstile/gotchas.md +218 -0
- package/skills/cloudflare/references/turnstile/patterns.md +193 -0
- package/skills/cloudflare/references/vectorize/README.md +133 -0
- package/skills/cloudflare/references/vectorize/api.md +88 -0
- package/skills/cloudflare/references/vectorize/configuration.md +88 -0
- package/skills/cloudflare/references/vectorize/gotchas.md +76 -0
- package/skills/cloudflare/references/vectorize/patterns.md +90 -0
- package/skills/cloudflare/references/waf/README.md +113 -0
- package/skills/cloudflare/references/waf/api.md +202 -0
- package/skills/cloudflare/references/waf/configuration.md +203 -0
- package/skills/cloudflare/references/waf/gotchas.md +204 -0
- package/skills/cloudflare/references/waf/patterns.md +197 -0
- package/skills/cloudflare/references/web-analytics/README.md +141 -0
- package/skills/cloudflare/references/web-analytics/configuration.md +76 -0
- package/skills/cloudflare/references/web-analytics/gotchas.md +82 -0
- package/skills/cloudflare/references/web-analytics/integration.md +60 -0
- package/skills/cloudflare/references/web-analytics/patterns.md +91 -0
- package/skills/cloudflare/references/workerd/README.md +78 -0
- package/skills/cloudflare/references/workerd/api.md +185 -0
- package/skills/cloudflare/references/workerd/configuration.md +183 -0
- package/skills/cloudflare/references/workerd/gotchas.md +139 -0
- package/skills/cloudflare/references/workerd/patterns.md +192 -0
- package/skills/cloudflare/references/workers/README.md +108 -0
- package/skills/cloudflare/references/workers/api.md +195 -0
- package/skills/cloudflare/references/workers/configuration.md +185 -0
- package/skills/cloudflare/references/workers/frameworks.md +197 -0
- package/skills/cloudflare/references/workers/gotchas.md +137 -0
- package/skills/cloudflare/references/workers/patterns.md +198 -0
- package/skills/cloudflare/references/workers-ai/README.md +197 -0
- package/skills/cloudflare/references/workers-ai/api.md +112 -0
- package/skills/cloudflare/references/workers-ai/configuration.md +97 -0
- package/skills/cloudflare/references/workers-ai/gotchas.md +114 -0
- package/skills/cloudflare/references/workers-ai/patterns.md +120 -0
- package/skills/cloudflare/references/workers-for-platforms/README.md +89 -0
- package/skills/cloudflare/references/workers-for-platforms/api.md +196 -0
- package/skills/cloudflare/references/workers-for-platforms/configuration.md +167 -0
- package/skills/cloudflare/references/workers-for-platforms/gotchas.md +134 -0
- package/skills/cloudflare/references/workers-for-platforms/patterns.md +188 -0
- package/skills/cloudflare/references/workers-playground/README.md +127 -0
- package/skills/cloudflare/references/workers-playground/api.md +101 -0
- package/skills/cloudflare/references/workers-playground/configuration.md +163 -0
- package/skills/cloudflare/references/workers-playground/gotchas.md +88 -0
- package/skills/cloudflare/references/workers-playground/patterns.md +132 -0
- package/skills/cloudflare/references/workers-vpc/README.md +127 -0
- package/skills/cloudflare/references/workers-vpc/api.md +202 -0
- package/skills/cloudflare/references/workers-vpc/configuration.md +147 -0
- package/skills/cloudflare/references/workers-vpc/gotchas.md +167 -0
- package/skills/cloudflare/references/workers-vpc/patterns.md +209 -0
- package/skills/cloudflare/references/workflows/README.md +77 -0
- package/skills/cloudflare/references/workflows/api.md +218 -0
- package/skills/cloudflare/references/workflows/configuration.md +152 -0
- package/skills/cloudflare/references/workflows/gotchas.md +90 -0
- package/skills/cloudflare/references/workflows/patterns.md +175 -0
- package/skills/cloudflare/references/wrangler/README.md +135 -0
- package/skills/cloudflare/references/wrangler/api.md +188 -0
- package/skills/cloudflare/references/wrangler/configuration.md +197 -0
- package/skills/cloudflare/references/wrangler/gotchas.md +197 -0
- package/skills/cloudflare/references/wrangler/patterns.md +209 -0
- package/skills/cloudflare/references/zaraz/IMPLEMENTATION_SUMMARY.md +121 -0
- package/skills/cloudflare/references/zaraz/README.md +111 -0
- package/skills/cloudflare/references/zaraz/api.md +112 -0
- package/skills/cloudflare/references/zaraz/configuration.md +90 -0
- package/skills/cloudflare/references/zaraz/gotchas.md +81 -0
- package/skills/cloudflare/references/zaraz/patterns.md +74 -0
- package/skills/cloudflare-email-service/SKILL.md +103 -0
- package/skills/cloudflare-email-service/references/cli-and-mcp.md +125 -0
- package/skills/cloudflare-email-service/references/deliverability.md +285 -0
- package/skills/cloudflare-email-service/references/rest-api.md +184 -0
- package/skills/cloudflare-email-service/references/routing.md +199 -0
- package/skills/cloudflare-email-service/references/sending.md +252 -0
- package/skills/cloudflare-one/SKILL.md +176 -0
- package/skills/cloudflare-one-migrations/SKILL.md +110 -0
- package/skills/durable-objects/SKILL.md +186 -0
- package/skills/durable-objects/references/rules.md +295 -0
- package/skills/durable-objects/references/testing.md +264 -0
- package/skills/durable-objects/references/workers.md +346 -0
- package/skills/sandbox-migrate-to-next/SKILL.md +185 -0
- package/skills/sandbox-next/SKILL.md +91 -0
- package/skills/sandbox-next/references/api-quick-ref.md +94 -0
- package/skills/sandbox-next/references/examples.md +15 -0
- package/skills/sandbox-stable/SKILL.md +110 -0
- package/skills/turnstile-spin/README.md +51 -0
- package/skills/turnstile-spin/SKILL.md +330 -0
- package/skills/turnstile-spin/references/astro.md +199 -0
- package/skills/turnstile-spin/references/hugo.md +114 -0
- package/skills/turnstile-spin/references/nextjs-app.md +261 -0
- package/skills/turnstile-spin/references/nextjs-pages.md +82 -0
- package/skills/turnstile-spin/references/sveltekit.md +191 -0
- package/skills/turnstile-spin/references/vanilla-html.md +157 -0
- package/skills/turnstile-spin/scripts/auth-probe.sh +285 -0
- package/skills/turnstile-spin/scripts/persist-skill.sh +114 -0
- package/skills/turnstile-spin/scripts/validate.sh +137 -0
- package/skills/turnstile-spin/scripts/widget-create.sh +121 -0
- package/skills/turnstile-spin/tests/validation.md +62 -0
- package/skills/workers-best-practices/SKILL.md +127 -0
- package/skills/workers-best-practices/references/review.md +174 -0
- package/skills/workers-best-practices/references/rules.md +467 -0
- package/skills/wrangler/SKILL.md +922 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# R2 API Reference
|
|
2
|
+
|
|
3
|
+
## PUT (Upload)
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// Basic
|
|
7
|
+
await env.MY_BUCKET.put(key, value);
|
|
8
|
+
|
|
9
|
+
// With metadata
|
|
10
|
+
await env.MY_BUCKET.put(key, value, {
|
|
11
|
+
httpMetadata: {
|
|
12
|
+
contentType: 'image/jpeg',
|
|
13
|
+
contentDisposition: 'attachment; filename="photo.jpg"',
|
|
14
|
+
cacheControl: 'max-age=3600'
|
|
15
|
+
},
|
|
16
|
+
customMetadata: { userId: '123', version: '2' },
|
|
17
|
+
storageClass: 'Standard', // or 'InfrequentAccess'
|
|
18
|
+
sha256: arrayBufferOrHex, // Integrity check
|
|
19
|
+
ssecKey: arrayBuffer32bytes // SSE-C encryption
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Value types: ReadableStream | ArrayBuffer | string | Blob
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## GET (Download)
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
const object = await env.MY_BUCKET.get(key);
|
|
29
|
+
if (!object) return new Response('Not found', { status: 404 });
|
|
30
|
+
|
|
31
|
+
// Body: arrayBuffer(), text(), json(), blob(), body (ReadableStream)
|
|
32
|
+
|
|
33
|
+
// Ranged reads
|
|
34
|
+
const object = await env.MY_BUCKET.get(key, { range: { offset: 0, length: 1024 } });
|
|
35
|
+
|
|
36
|
+
// Conditional GET
|
|
37
|
+
const object = await env.MY_BUCKET.get(key, { onlyIf: { etagMatches: '"abc123"' } });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## HEAD (Metadata Only)
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const object = await env.MY_BUCKET.head(key); // Returns R2Object without body
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## DELETE
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
await env.MY_BUCKET.delete(key);
|
|
50
|
+
await env.MY_BUCKET.delete([key1, key2, key3]); // Batch (max 1000)
|
|
51
|
+
```
|
|
52
|
+
## LIST
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const listed = await env.MY_BUCKET.list({
|
|
56
|
+
limit: 1000,
|
|
57
|
+
prefix: 'photos/',
|
|
58
|
+
cursor: cursorFromPrevious,
|
|
59
|
+
delimiter: '/',
|
|
60
|
+
include: ['httpMetadata', 'customMetadata']
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Pagination (always use truncated flag)
|
|
64
|
+
while (listed.truncated) {
|
|
65
|
+
const next = await env.MY_BUCKET.list({ cursor: listed.cursor });
|
|
66
|
+
listed.objects.push(...next.objects);
|
|
67
|
+
listed.truncated = next.truncated;
|
|
68
|
+
listed.cursor = next.cursor;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Multipart Uploads
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const multipart = await env.MY_BUCKET.createMultipartUpload(key, {
|
|
76
|
+
httpMetadata: { contentType: 'video/mp4' }
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const uploadedParts: R2UploadedPart[] = [];
|
|
80
|
+
for (let i = 0; i < partCount; i++) {
|
|
81
|
+
const part = await multipart.uploadPart(i + 1, partData);
|
|
82
|
+
uploadedParts.push(part);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const object = await multipart.complete(uploadedParts);
|
|
86
|
+
// OR: await multipart.abort();
|
|
87
|
+
|
|
88
|
+
// Resume
|
|
89
|
+
const multipart = env.MY_BUCKET.resumeMultipartUpload(key, uploadId);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Presigned URLs (S3 SDK)
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
96
|
+
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
97
|
+
|
|
98
|
+
const s3 = new S3Client({
|
|
99
|
+
region: 'auto',
|
|
100
|
+
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
|
101
|
+
credentials: { accessKeyId: env.R2_ACCESS_KEY_ID, secretAccessKey: env.R2_SECRET_ACCESS_KEY }
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const uploadUrl = await getSignedUrl(s3, new PutObjectCommand({ Bucket: 'my-bucket', Key: key }), { expiresIn: 3600 });
|
|
105
|
+
return Response.json({ uploadUrl });
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## TypeScript Interfaces
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
interface R2Bucket {
|
|
112
|
+
head(key: string): Promise<R2Object | null>;
|
|
113
|
+
get(key: string, options?: R2GetOptions): Promise<R2ObjectBody | null>;
|
|
114
|
+
put(key: string, value: ReadableStream | ArrayBuffer | string | Blob, options?: R2PutOptions): Promise<R2Object | null>;
|
|
115
|
+
delete(keys: string | string[]): Promise<void>;
|
|
116
|
+
list(options?: R2ListOptions): Promise<R2Objects>;
|
|
117
|
+
createMultipartUpload(key: string, options?: R2MultipartOptions): Promise<R2MultipartUpload>;
|
|
118
|
+
resumeMultipartUpload(key: string, uploadId: string): R2MultipartUpload;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface R2Object {
|
|
122
|
+
key: string; version: string; size: number;
|
|
123
|
+
etag: string; httpEtag: string; // httpEtag is quoted, use for headers
|
|
124
|
+
uploaded: Date; httpMetadata?: R2HTTPMetadata;
|
|
125
|
+
customMetadata?: Record<string, string>;
|
|
126
|
+
storageClass: 'Standard' | 'InfrequentAccess';
|
|
127
|
+
checksums: R2Checksums;
|
|
128
|
+
writeHttpMetadata(headers: Headers): void;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface R2ObjectBody extends R2Object {
|
|
132
|
+
body: ReadableStream; bodyUsed: boolean;
|
|
133
|
+
arrayBuffer(): Promise<ArrayBuffer>; text(): Promise<string>;
|
|
134
|
+
json<T>(): Promise<T>; blob(): Promise<Blob>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface R2HTTPMetadata {
|
|
138
|
+
contentType?: string; contentDisposition?: string;
|
|
139
|
+
contentEncoding?: string; contentLanguage?: string;
|
|
140
|
+
cacheControl?: string; cacheExpiry?: Date;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface R2PutOptions {
|
|
144
|
+
httpMetadata?: R2HTTPMetadata | Headers;
|
|
145
|
+
customMetadata?: Record<string, string>;
|
|
146
|
+
sha256?: ArrayBuffer | string; // Only ONE checksum allowed
|
|
147
|
+
storageClass?: 'Standard' | 'InfrequentAccess';
|
|
148
|
+
ssecKey?: ArrayBuffer;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface R2GetOptions {
|
|
152
|
+
onlyIf?: R2Conditional | Headers;
|
|
153
|
+
range?: R2Range | Headers;
|
|
154
|
+
ssecKey?: ArrayBuffer;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface R2ListOptions {
|
|
158
|
+
limit?: number; prefix?: string; cursor?: string; delimiter?: string;
|
|
159
|
+
startAfter?: string; include?: ('httpMetadata' | 'customMetadata')[];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
interface R2Objects {
|
|
163
|
+
objects: R2Object[]; truncated: boolean;
|
|
164
|
+
cursor?: string; delimitedPrefixes: string[];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
interface R2Conditional {
|
|
168
|
+
etagMatches?: string; etagDoesNotMatch?: string;
|
|
169
|
+
uploadedBefore?: Date; uploadedAfter?: Date;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
interface R2Range { offset?: number; length?: number; suffix?: number; }
|
|
173
|
+
|
|
174
|
+
interface R2Checksums {
|
|
175
|
+
md5?: ArrayBuffer; sha1?: ArrayBuffer; sha256?: ArrayBuffer;
|
|
176
|
+
sha384?: ArrayBuffer; sha512?: ArrayBuffer;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
interface R2MultipartUpload {
|
|
180
|
+
key: string;
|
|
181
|
+
uploadId: string;
|
|
182
|
+
uploadPart(partNumber: number, value: ReadableStream | ArrayBuffer | string | Blob): Promise<R2UploadedPart>;
|
|
183
|
+
abort(): Promise<void>;
|
|
184
|
+
complete(uploadedParts: R2UploadedPart[]): Promise<R2Object>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
interface R2UploadedPart {
|
|
188
|
+
partNumber: number;
|
|
189
|
+
etag: string;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## CLI Operations
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
wrangler r2 object put my-bucket/file.txt --file=./local.txt
|
|
197
|
+
wrangler r2 object get my-bucket/file.txt --file=./download.txt
|
|
198
|
+
wrangler r2 object delete my-bucket/file.txt
|
|
199
|
+
wrangler r2 object list my-bucket --prefix=photos/
|
|
200
|
+
```
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# R2 Configuration
|
|
2
|
+
|
|
3
|
+
## Workers Binding
|
|
4
|
+
|
|
5
|
+
**wrangler.jsonc:**
|
|
6
|
+
```jsonc
|
|
7
|
+
{
|
|
8
|
+
"r2_buckets": [
|
|
9
|
+
{
|
|
10
|
+
"binding": "MY_BUCKET",
|
|
11
|
+
"bucket_name": "my-bucket-name"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## TypeScript Types
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
interface Env { MY_BUCKET: R2Bucket; }
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
24
|
+
const object = await env.MY_BUCKET.get('file.txt');
|
|
25
|
+
return new Response(object?.body);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## S3 SDK Setup
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
34
|
+
|
|
35
|
+
const s3 = new S3Client({
|
|
36
|
+
region: 'auto',
|
|
37
|
+
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
|
38
|
+
credentials: {
|
|
39
|
+
accessKeyId: env.R2_ACCESS_KEY_ID,
|
|
40
|
+
secretAccessKey: env.R2_SECRET_ACCESS_KEY
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await s3.send(new PutObjectCommand({
|
|
45
|
+
Bucket: 'my-bucket',
|
|
46
|
+
Key: 'file.txt',
|
|
47
|
+
Body: data,
|
|
48
|
+
StorageClass: 'STANDARD' // or 'STANDARD_IA'
|
|
49
|
+
}));
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Location Hints
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
wrangler r2 bucket create my-bucket --location=enam
|
|
56
|
+
|
|
57
|
+
# Hints: wnam, enam, weur, eeur, apac, oc
|
|
58
|
+
# Jurisdictions (override hint): --jurisdiction=eu (or fedramp)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## CORS Configuration
|
|
62
|
+
|
|
63
|
+
CORS must be configured via S3 SDK or dashboard (not available in Workers API):
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { S3Client, PutBucketCorsCommand } from '@aws-sdk/client-s3';
|
|
67
|
+
|
|
68
|
+
const s3 = new S3Client({
|
|
69
|
+
region: 'auto',
|
|
70
|
+
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
|
71
|
+
credentials: {
|
|
72
|
+
accessKeyId: env.R2_ACCESS_KEY_ID,
|
|
73
|
+
secretAccessKey: env.R2_SECRET_ACCESS_KEY
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await s3.send(new PutBucketCorsCommand({
|
|
78
|
+
Bucket: 'my-bucket',
|
|
79
|
+
CORSConfiguration: {
|
|
80
|
+
CORSRules: [{
|
|
81
|
+
AllowedOrigins: ['https://example.com'],
|
|
82
|
+
AllowedMethods: ['GET', 'PUT', 'HEAD'],
|
|
83
|
+
AllowedHeaders: ['*'],
|
|
84
|
+
ExposeHeaders: ['ETag'],
|
|
85
|
+
MaxAgeSeconds: 3600
|
|
86
|
+
}]
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Object Lifecycles
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { PutBucketLifecycleConfigurationCommand } from '@aws-sdk/client-s3';
|
|
95
|
+
|
|
96
|
+
await s3.send(new PutBucketLifecycleConfigurationCommand({
|
|
97
|
+
Bucket: 'my-bucket',
|
|
98
|
+
LifecycleConfiguration: {
|
|
99
|
+
Rules: [
|
|
100
|
+
{
|
|
101
|
+
ID: 'expire-old-logs',
|
|
102
|
+
Status: 'Enabled',
|
|
103
|
+
Prefix: 'logs/',
|
|
104
|
+
Expiration: { Days: 90 }
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
ID: 'transition-to-ia',
|
|
108
|
+
Status: 'Enabled',
|
|
109
|
+
Prefix: 'archives/',
|
|
110
|
+
Transitions: [{ Days: 30, StorageClass: 'STANDARD_IA' }]
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
}));
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## API Token Scopes
|
|
118
|
+
|
|
119
|
+
When creating R2 tokens, set minimal permissions:
|
|
120
|
+
|
|
121
|
+
| Permission | Use Case |
|
|
122
|
+
|------------|----------|
|
|
123
|
+
| Object Read | Public serving, downloads |
|
|
124
|
+
| Object Write | Uploads only |
|
|
125
|
+
| Object Read & Write | Full object operations |
|
|
126
|
+
| Admin Read & Write | Bucket management, CORS, lifecycles |
|
|
127
|
+
|
|
128
|
+
**Best practice:** Separate tokens for Workers (read/write) vs admin tasks (CORS, lifecycles).
|
|
129
|
+
|
|
130
|
+
## Event Notifications
|
|
131
|
+
|
|
132
|
+
```jsonc
|
|
133
|
+
// wrangler.jsonc
|
|
134
|
+
{
|
|
135
|
+
"r2_buckets": [
|
|
136
|
+
{
|
|
137
|
+
"binding": "MY_BUCKET",
|
|
138
|
+
"bucket_name": "my-bucket",
|
|
139
|
+
"event_notifications": [
|
|
140
|
+
{
|
|
141
|
+
"queue": "r2-events",
|
|
142
|
+
"actions": ["PutObject", "DeleteObject", "CompleteMultipartUpload"]
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"queues": {
|
|
148
|
+
"producers": [{ "binding": "R2_EVENTS", "queue": "r2-events" }],
|
|
149
|
+
"consumers": [{ "queue": "r2-events", "max_batch_size": 10 }]
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Bucket Management
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
wrangler r2 bucket create my-bucket --location=enam --storage-class=Standard
|
|
158
|
+
wrangler r2 bucket list
|
|
159
|
+
wrangler r2 bucket info my-bucket
|
|
160
|
+
wrangler r2 bucket delete my-bucket # Must be empty
|
|
161
|
+
wrangler r2 bucket update-storage-class my-bucket --storage-class=InfrequentAccess
|
|
162
|
+
|
|
163
|
+
# Public bucket via dashboard
|
|
164
|
+
wrangler r2 bucket domain add my-bucket --domain=files.example.com
|
|
165
|
+
```
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# R2 Gotchas & Troubleshooting
|
|
2
|
+
|
|
3
|
+
## List Truncation
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// ❌ WRONG: Don't compare object count when using include
|
|
7
|
+
while (listed.objects.length < options.limit) { ... }
|
|
8
|
+
|
|
9
|
+
// ✅ CORRECT: Always use truncated property
|
|
10
|
+
while (listed.truncated) {
|
|
11
|
+
const next = await env.MY_BUCKET.list({ cursor: listed.cursor });
|
|
12
|
+
// ...
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Reason:** `include` with metadata may return fewer objects per page to fit metadata.
|
|
17
|
+
|
|
18
|
+
## ETag Format
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// ❌ WRONG: Using etag (unquoted) in headers
|
|
22
|
+
headers.set('etag', object.etag); // Missing quotes
|
|
23
|
+
|
|
24
|
+
// ✅ CORRECT: Use httpEtag (quoted)
|
|
25
|
+
headers.set('etag', object.httpEtag);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Checksum Limits
|
|
29
|
+
|
|
30
|
+
Only ONE checksum algorithm allowed per PUT:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// ❌ WRONG: Multiple checksums
|
|
34
|
+
await env.MY_BUCKET.put(key, data, { md5: hash1, sha256: hash2 }); // Error
|
|
35
|
+
|
|
36
|
+
// ✅ CORRECT: Pick one
|
|
37
|
+
await env.MY_BUCKET.put(key, data, { sha256: hash });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Multipart Requirements
|
|
41
|
+
|
|
42
|
+
- All parts must be uniform size (except last part)
|
|
43
|
+
- Part numbers start at 1 (not 0)
|
|
44
|
+
- Uncompleted uploads auto-abort after 7 days
|
|
45
|
+
- `resumeMultipartUpload` doesn't validate uploadId existence
|
|
46
|
+
|
|
47
|
+
## Conditional Operations
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Precondition failure returns object WITHOUT body
|
|
51
|
+
const object = await env.MY_BUCKET.get(key, {
|
|
52
|
+
onlyIf: { etagMatches: '"wrong"' }
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Check for body, not just null
|
|
56
|
+
if (!object) return new Response('Not found', { status: 404 });
|
|
57
|
+
if (!object.body) return new Response(null, { status: 304 }); // Precondition failed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Key Validation
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// ❌ DANGEROUS: Path traversal
|
|
64
|
+
const key = url.pathname.slice(1); // Could be ../../../etc/passwd
|
|
65
|
+
await env.MY_BUCKET.get(key);
|
|
66
|
+
|
|
67
|
+
// ✅ SAFE: Validate keys
|
|
68
|
+
if (!key || key.includes('..') || key.startsWith('/')) {
|
|
69
|
+
return new Response('Invalid key', { status: 400 });
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Storage Class Pitfalls
|
|
74
|
+
|
|
75
|
+
- InfrequentAccess: 30-day minimum billing (even if deleted early)
|
|
76
|
+
- Can't transition IA → Standard via lifecycle (use S3 CopyObject)
|
|
77
|
+
- Retrieval fees apply for IA reads
|
|
78
|
+
|
|
79
|
+
## Stream Length Requirement
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// ❌ WRONG: Streaming unknown length fails silently
|
|
83
|
+
const response = await fetch(url);
|
|
84
|
+
await env.MY_BUCKET.put(key, response.body); // May fail without error
|
|
85
|
+
|
|
86
|
+
// ✅ CORRECT: Buffer or use Content-Length
|
|
87
|
+
const data = await response.arrayBuffer();
|
|
88
|
+
await env.MY_BUCKET.put(key, data);
|
|
89
|
+
|
|
90
|
+
// OR: Pass Content-Length if known
|
|
91
|
+
const object = await env.MY_BUCKET.put(key, request.body, {
|
|
92
|
+
httpMetadata: {
|
|
93
|
+
contentLength: parseInt(request.headers.get('content-length') || '0')
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Reason:** R2 requires known length for streams. Unknown length may cause silent truncation.
|
|
99
|
+
|
|
100
|
+
## S3 SDK Region Configuration
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// ❌ WRONG: Missing region breaks ALL S3 SDK calls
|
|
104
|
+
const s3 = new S3Client({
|
|
105
|
+
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
|
106
|
+
credentials: { ... }
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// ✅ CORRECT: MUST set region='auto'
|
|
110
|
+
const s3 = new S3Client({
|
|
111
|
+
region: 'auto', // REQUIRED
|
|
112
|
+
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
|
113
|
+
credentials: { ... }
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Reason:** S3 SDK requires region. R2 uses 'auto' as placeholder.
|
|
118
|
+
|
|
119
|
+
## Local Development Limits
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// ❌ Miniflare/wrangler dev: Limited R2 support
|
|
123
|
+
// - No multipart uploads
|
|
124
|
+
// - No presigned URLs (requires S3 SDK + network)
|
|
125
|
+
// - Memory-backed storage (lost on restart)
|
|
126
|
+
|
|
127
|
+
// ✅ Use remote bindings for full features
|
|
128
|
+
wrangler dev --remote
|
|
129
|
+
|
|
130
|
+
// OR: Conditional logic
|
|
131
|
+
if (env.ENVIRONMENT === 'development') {
|
|
132
|
+
// Fallback for local dev
|
|
133
|
+
} else {
|
|
134
|
+
// Full R2 features
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Presigned URL Expiry
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// ❌ WRONG: URL expires but no client validation
|
|
142
|
+
const url = await getSignedUrl(s3, command, { expiresIn: 60 });
|
|
143
|
+
// 61 seconds later: 403 Forbidden
|
|
144
|
+
|
|
145
|
+
// ✅ CORRECT: Return expiry to client
|
|
146
|
+
return Response.json({
|
|
147
|
+
uploadUrl: url,
|
|
148
|
+
expiresAt: new Date(Date.now() + 60000).toISOString()
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Limits
|
|
153
|
+
|
|
154
|
+
| Limit | Value |
|
|
155
|
+
|-------|-------|
|
|
156
|
+
| Object size | 5 TB |
|
|
157
|
+
| Multipart part count | 10,000 |
|
|
158
|
+
| Multipart part min size | 5 MB (except last) |
|
|
159
|
+
| Batch delete | 1,000 keys |
|
|
160
|
+
| List limit | 1,000 per request |
|
|
161
|
+
| Key size | 1024 bytes |
|
|
162
|
+
| Custom metadata | 2 KB per object |
|
|
163
|
+
| Presigned URL max expiry | 7 days |
|
|
164
|
+
|
|
165
|
+
## Common Errors
|
|
166
|
+
|
|
167
|
+
### "Stream upload failed" / Silent Truncation
|
|
168
|
+
|
|
169
|
+
**Cause:** Stream length unknown or Content-Length missing
|
|
170
|
+
**Solution:** Buffer data or pass explicit Content-Length
|
|
171
|
+
|
|
172
|
+
### "Invalid credentials" / S3 SDK
|
|
173
|
+
|
|
174
|
+
**Cause:** Missing `region: 'auto'` in S3Client config
|
|
175
|
+
**Solution:** Always set `region: 'auto'` for R2
|
|
176
|
+
|
|
177
|
+
### "Object not found"
|
|
178
|
+
|
|
179
|
+
**Cause:** Object key doesn't exist or was deleted
|
|
180
|
+
**Solution:** Verify object key correct, check if object was deleted, ensure bucket correct
|
|
181
|
+
|
|
182
|
+
### "List compatibility error"
|
|
183
|
+
|
|
184
|
+
**Cause:** Missing or old compatibility_date, or flag not enabled
|
|
185
|
+
**Solution:** Set `compatibility_date >= 2022-08-04` or enable `r2_list_honor_include` flag
|
|
186
|
+
|
|
187
|
+
### "Multipart upload failed"
|
|
188
|
+
|
|
189
|
+
**Cause:** Part sizes not uniform or incorrect part number
|
|
190
|
+
**Solution:** Ensure uniform size except final part, verify part numbers start at 1
|