opencodekit 0.15.4 → 0.15.5
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/dist/index.js +1 -1
- package/dist/template/.opencode/command/cloudflare.md +70 -0
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/skill/cloudflare/SKILL.md +233 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/README.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/api.md +100 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/configuration.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/gotchas.md +59 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/patterns.md +89 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-gateway/README.md +695 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/api.md +38 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/configuration.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/gotchas.md +41 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/patterns.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/api.md +27 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/configuration.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/gotchas.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/patterns.md +36 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/README.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/api.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/configuration.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/gotchas.md +28 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/patterns.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/README.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/api.md +78 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/configuration.md +128 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/gotchas.md +51 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/patterns.md +145 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/api.md +50 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/configuration.md +53 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/gotchas.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/patterns.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/configuration.md +58 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/gotchas.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/patterns.md +37 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/README.md +71 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/api.md +168 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/configuration.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/gotchas.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/patterns.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/api.md +54 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/configuration.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/gotchas.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/patterns.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/c3/README.md +264 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/README.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/api.md +176 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/configuration.md +164 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/gotchas.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/patterns.md +180 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/api.md +43 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/configuration.md +56 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/gotchas.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/patterns.md +40 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/README.md +85 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/api.md +198 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/configuration.md +151 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/gotchas.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/patterns.md +122 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/README.md +92 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/api.md +141 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/gotchas.md +70 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/patterns.md +144 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/README.md +34 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/api.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/configuration.md +67 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/gotchas.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/patterns.md +158 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/api.md +89 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/configuration.md +116 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/gotchas.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/patterns.md +112 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/README.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/api.md +152 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/configuration.md +148 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/gotchas.md +158 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/patterns.md +255 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/api.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/configuration.md +63 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/gotchas.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/patterns.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-workers/README.md +598 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/api.md +137 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/configuration.md +133 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/gotchas.md +184 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/patterns.md +176 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/configuration.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/gotchas.md +23 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/patterns.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/README.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/api.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/configuration.md +92 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/gotchas.md +117 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/patterns.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/README.md +64 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/api.md +144 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/configuration.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/gotchas.md +187 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/patterns.md +211 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/README.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/api.md +240 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/gotchas.md +171 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/patterns.md +171 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/api.md +51 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/configuration.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/gotchas.md +36 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/README.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/api.md +200 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/configuration.md +228 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/gotchas.md +161 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/patterns.md +145 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/README.md +57 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/api.md +201 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/configuration.md +159 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/gotchas.md +151 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/patterns.md +190 -0
- package/dist/template/.opencode/skill/cloudflare/references/pipelines/README.md +664 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/README.md +107 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/api.md +194 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/configuration.md +216 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/gotchas.md +223 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/patterns.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/README.md +69 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/api.md +138 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/configuration.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/gotchas.md +112 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/patterns.md +155 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/README.md +61 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/api.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/configuration.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/gotchas.md +94 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/patterns.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/api.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/configuration.md +39 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/gotchas.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/patterns.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-sql/README.md +512 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/README.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/api.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/configuration.md +63 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/gotchas.md +75 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/patterns.md +102 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/README.md +81 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/api.md +164 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/configuration.md +147 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/gotchas.md +172 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/patterns.md +155 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/README.md +90 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/api.md +178 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/configuration.md +131 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/gotchas.md +156 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/patterns.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/README.md +58 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/api.md +182 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/configuration.md +140 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/gotchas.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/patterns.md +218 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/README.md +91 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/api.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/configuration.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/gotchas.md +87 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/patterns.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/README.md +15 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/api.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/configuration.md +33 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/gotchas.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/patterns.md +34 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/api.md +24 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/configuration.md +43 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/gotchas.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/patterns.md +40 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/configuration.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/gotchas.md +44 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/README.md +103 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/api.md +204 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/gotchas.md +131 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/patterns.md +152 -0
- package/dist/template/.opencode/skill/cloudflare/references/tail-workers/README.md +640 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/README.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/api.md +159 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/configuration.md +156 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/gotchas.md +207 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/patterns.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/README.md +82 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/api.md +105 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/configuration.md +113 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/gotchas.md +115 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/patterns.md +157 -0
- package/dist/template/.opencode/skill/cloudflare/references/turn/README.md +699 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/configuration.md +19 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/gotchas.md +27 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/patterns.md +41 -0
- package/dist/template/.opencode/skill/cloudflare/references/vectorize/README.md +682 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/configuration.md +44 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/gotchas.md +24 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/patterns.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/README.md +19 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/api.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/configuration.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/gotchas.md +28 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/patterns.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/README.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/api.md +199 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/configuration.md +185 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/gotchas.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/patterns.md +216 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/README.md +96 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/api.md +137 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/configuration.md +147 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/gotchas.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/patterns.md +149 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-ai/README.md +116 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/README.md +48 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/api.md +169 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/configuration.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/gotchas.md +130 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/patterns.md +170 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/api.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/configuration.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/gotchas.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-vpc/README.md +579 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/api.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/configuration.md +177 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/gotchas.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/patterns.md +132 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/README.md +90 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/api.md +140 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/configuration.md +128 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/gotchas.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/patterns.md +150 -0
- package/dist/template/.opencode/skill/cloudflare/references/zaraz/README.md +360 -0
- package/dist/template/.opencode/skill/react-best-practices/AGENTS.md +2410 -0
- package/dist/template/.opencode/skill/react-best-practices/README.md +123 -0
- package/dist/template/.opencode/skill/react-best-practices/SKILL.md +125 -0
- package/dist/template/.opencode/skill/react-best-practices/metadata.json +15 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/_sections.md +46 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/_template.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-api-routes.md +38 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-defer-await.md +80 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-dependencies.md +36 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-parallel.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-conditional.md +31 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-preload.md +50 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-event-listeners.md +74 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-storage.md +70 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-early-exit.md +50 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-index-maps.md +37 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-length-check-first.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-activity.md +26 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-memo.md +44 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-transitions.md +40 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-lru.md +41 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-react.md +76 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-serialization.md +38 -0
- package/dist/template/.opencode/skill/supabase/SKILL.md +120 -0
- package/dist/template/.opencode/skill/supabase/mcp.json +27 -0
- package/dist/template/.opencode/skill/vercel-deploy-claimable/SKILL.md +112 -0
- package/dist/template/.opencode/skill/vercel-deploy-claimable/scripts/deploy.sh +249 -0
- package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +39 -0
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
## Common Use Cases
|
|
2
|
+
|
|
3
|
+
### 1. API Gateway
|
|
4
|
+
```javascript
|
|
5
|
+
export default {
|
|
6
|
+
async fetch(request, env, ctx) {
|
|
7
|
+
const url = new URL(request.url);
|
|
8
|
+
|
|
9
|
+
// Route based on path
|
|
10
|
+
if (url.pathname.startsWith('/v1/users')) {
|
|
11
|
+
return fetch('https://users-api.example.com' + url.pathname);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (url.pathname.startsWith('/v1/posts')) {
|
|
15
|
+
return fetch('https://posts-api.example.com' + url.pathname);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return new Response('API Gateway', { status: 404 });
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 2. A/B Testing
|
|
24
|
+
```javascript
|
|
25
|
+
export default {
|
|
26
|
+
async fetch(request, env, ctx) {
|
|
27
|
+
const url = new URL(request.url);
|
|
28
|
+
const cookie = request.headers.get('Cookie');
|
|
29
|
+
|
|
30
|
+
// Check existing variant
|
|
31
|
+
let variant = cookie?.includes('ab_test=B') ? 'B' : null;
|
|
32
|
+
|
|
33
|
+
if (!variant) {
|
|
34
|
+
// Assign 50/50 split
|
|
35
|
+
variant = Math.random() < 0.5 ? 'A' : 'B';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const targetUrl = variant === 'A'
|
|
39
|
+
? 'https://a.example.com'
|
|
40
|
+
: 'https://b.example.com';
|
|
41
|
+
|
|
42
|
+
con
|
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
# Cloudflare Workers VPC Skill
|
|
2
|
+
|
|
3
|
+
Expert guidance for connecting Cloudflare Workers to private networks (AWS/Azure/GCP/on-prem) using TCP Sockets, Cloudflare Tunnel, and related technologies.
|
|
4
|
+
|
|
5
|
+
## What is Workers VPC Connectivity?
|
|
6
|
+
|
|
7
|
+
Workers VPC connectivity enables Workers to communicate with resources in private networks through:
|
|
8
|
+
|
|
9
|
+
1. **TCP Sockets API** (`connect()`) - Direct outbound TCP connections from Workers
|
|
10
|
+
2. **Cloudflare Tunnel** - Secure connections to private networks without exposing public IPs
|
|
11
|
+
3. **Hyperdrive** - Optimized connections to external databases with pooling
|
|
12
|
+
4. **Smart Placement** - Automatic Worker placement near backend services
|
|
13
|
+
|
|
14
|
+
## Core APIs
|
|
15
|
+
|
|
16
|
+
### TCP Sockets (`connect()`)
|
|
17
|
+
|
|
18
|
+
Create outbound TCP connections to private resources:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { connect } from 'cloudflare:sockets';
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
async fetch(req: Request): Promise<Response> {
|
|
25
|
+
const socket = connect({
|
|
26
|
+
hostname: "internal-db.private.com",
|
|
27
|
+
port: 5432
|
|
28
|
+
}, {
|
|
29
|
+
secureTransport: "starttls" // or "on" for immediate TLS
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Get readable/writable streams
|
|
33
|
+
const writer = socket.writable.getWriter();
|
|
34
|
+
const reader = socket.readable.getReader();
|
|
35
|
+
|
|
36
|
+
// Write data
|
|
37
|
+
const encoder = new TextEncoder();
|
|
38
|
+
await writer.write(encoder.encode("QUERY\r\n"));
|
|
39
|
+
await writer.close();
|
|
40
|
+
|
|
41
|
+
// Read response
|
|
42
|
+
const { value } = await reader.read();
|
|
43
|
+
|
|
44
|
+
await socket.close();
|
|
45
|
+
return new Response(value);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### SocketOptions
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
interface SocketOptions {
|
|
54
|
+
secureTransport?: "off" | "on" | "starttls"; // Default: "off"
|
|
55
|
+
allowHalfOpen?: boolean; // Default: false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface SocketAddress {
|
|
59
|
+
hostname: string; // e.g., "db.private.net"
|
|
60
|
+
port: number; // e.g., 5432
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Socket Interface
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
interface Socket {
|
|
68
|
+
readable: ReadableStream<Uint8Array>;
|
|
69
|
+
writable: WritableStream<Uint8Array>;
|
|
70
|
+
opened: Promise<SocketInfo>;
|
|
71
|
+
closed: Promise<void>;
|
|
72
|
+
close(): Promise<void>;
|
|
73
|
+
startTls(): Socket; // Upgrade to TLS
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Common Use Cases
|
|
78
|
+
|
|
79
|
+
### 1. Connect to Internal Database
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { connect } from 'cloudflare:sockets';
|
|
83
|
+
|
|
84
|
+
export default {
|
|
85
|
+
async fetch(req: Request) {
|
|
86
|
+
const socket = connect(
|
|
87
|
+
{ hostname: "10.0.1.50", port: 5432 },
|
|
88
|
+
{ secureTransport: "on" }
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await socket.opened; // Wait for connection
|
|
93
|
+
|
|
94
|
+
const writer = socket.writable.getWriter();
|
|
95
|
+
await writer.write(new TextEncoder().encode("SELECT 1\n"));
|
|
96
|
+
await writer.close();
|
|
97
|
+
|
|
98
|
+
return new Response(socket.readable);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return new Response(`Connection failed: ${error}`, { status: 500 });
|
|
101
|
+
} finally {
|
|
102
|
+
await socket.close();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 2. StartTLS Pattern (Opportunistic TLS)
|
|
109
|
+
|
|
110
|
+
Many databases require starting insecure then upgrading:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { connect } from 'cloudflare:sockets';
|
|
114
|
+
|
|
115
|
+
const socket = connect(
|
|
116
|
+
{ hostname: "postgres.internal", port: 5432 },
|
|
117
|
+
{ secureTransport: "starttls" }
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// Initially insecure connection
|
|
121
|
+
const writer = socket.writable.getWriter();
|
|
122
|
+
await writer.write(new TextEncoder().encode("STARTTLS\n"));
|
|
123
|
+
|
|
124
|
+
// Upgrade to TLS
|
|
125
|
+
const secureSocket = socket.startTls();
|
|
126
|
+
|
|
127
|
+
// Now use secureSocket for encrypted communication
|
|
128
|
+
const secureWriter = secureSocket.writable.getWriter();
|
|
129
|
+
await secureWriter.write(new TextEncoder().encode("AUTH\n"));
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 3. SSH/MQTT/SMTP Protocols
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// SSH connection example
|
|
136
|
+
import { connect } from 'cloudflare:sockets';
|
|
137
|
+
|
|
138
|
+
export default {
|
|
139
|
+
async fetch(req: Request) {
|
|
140
|
+
const socket = connect(
|
|
141
|
+
{ hostname: "bastion.internal", port: 22 },
|
|
142
|
+
{ secureTransport: "on" }
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const writer = socket.writable.getWriter();
|
|
146
|
+
const reader = socket.readable.getReader();
|
|
147
|
+
|
|
148
|
+
// SSH handshake
|
|
149
|
+
await writer.write(new TextEncoder().encode("SSH-2.0-CloudflareWorker\r\n"));
|
|
150
|
+
|
|
151
|
+
// Read server response
|
|
152
|
+
const { value } = await reader.read();
|
|
153
|
+
const response = new TextDecoder().decode(value);
|
|
154
|
+
|
|
155
|
+
await socket.close();
|
|
156
|
+
return new Response(response);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 4. Connection with Error Handling
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { connect } from 'cloudflare:sockets';
|
|
165
|
+
|
|
166
|
+
async function connectToPrivateService(
|
|
167
|
+
host: string,
|
|
168
|
+
port: number,
|
|
169
|
+
data: string
|
|
170
|
+
): Promise<string> {
|
|
171
|
+
let socket: ReturnType<typeof connect> | null = null;
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
socket = connect({ hostname: host, port }, { secureTransport: "on" });
|
|
175
|
+
|
|
176
|
+
await socket.opened; // Throws if connection fails
|
|
177
|
+
|
|
178
|
+
const writer = socket.writable.getWriter();
|
|
179
|
+
await writer.write(new TextEncoder().encode(data));
|
|
180
|
+
await writer.close();
|
|
181
|
+
|
|
182
|
+
const reader = socket.readable.getReader();
|
|
183
|
+
const chunks: Uint8Array[] = [];
|
|
184
|
+
|
|
185
|
+
while (true) {
|
|
186
|
+
const { done, value } = await reader.read();
|
|
187
|
+
if (done) break;
|
|
188
|
+
chunks.push(value);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const combined = new Uint8Array(
|
|
192
|
+
chunks.reduce((acc, chunk) => acc + chunk.length, 0)
|
|
193
|
+
);
|
|
194
|
+
let offset = 0;
|
|
195
|
+
chunks.forEach(chunk => {
|
|
196
|
+
combined.set(chunk, offset);
|
|
197
|
+
offset += chunk.length;
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return new TextDecoder().decode(combined);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
throw new Error(`Socket error: ${error}`);
|
|
203
|
+
} finally {
|
|
204
|
+
if (socket) await socket.close();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Integration with Cloudflare Tunnel
|
|
210
|
+
|
|
211
|
+
Connect Workers to private networks via Cloudflare Tunnel:
|
|
212
|
+
|
|
213
|
+
### Architecture Pattern
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
Worker → TCP Socket → Cloudflare Tunnel → Private Network
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Setup
|
|
220
|
+
|
|
221
|
+
1. **Install cloudflared in your private network:**
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# On private network server
|
|
225
|
+
cloudflared tunnel create my-private-network
|
|
226
|
+
cloudflared tunnel route ip add 10.0.0.0/24 my-private-network
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
2. **Configure tunnel:**
|
|
230
|
+
|
|
231
|
+
```yaml
|
|
232
|
+
# config.yml
|
|
233
|
+
tunnel: <TUNNEL_ID>
|
|
234
|
+
credentials-file: /path/to/credentials.json
|
|
235
|
+
|
|
236
|
+
ingress:
|
|
237
|
+
- hostname: db.internal.example.com
|
|
238
|
+
service: tcp://10.0.1.50:5432
|
|
239
|
+
- hostname: api.internal.example.com
|
|
240
|
+
service: http://10.0.1.100:8080
|
|
241
|
+
- service: http_status:404
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
3. **Connect from Worker:**
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import { connect } from 'cloudflare:sockets';
|
|
248
|
+
|
|
249
|
+
export default {
|
|
250
|
+
async fetch(req: Request) {
|
|
251
|
+
// Connect through Tunnel to private resource
|
|
252
|
+
const socket = connect({
|
|
253
|
+
hostname: "db.internal.example.com",
|
|
254
|
+
port: 5432
|
|
255
|
+
}, {
|
|
256
|
+
secureTransport: "on"
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// Use socket...
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Wrangler Configuration
|
|
265
|
+
|
|
266
|
+
### Enable TCP Sockets
|
|
267
|
+
|
|
268
|
+
```toml
|
|
269
|
+
# wrangler.toml
|
|
270
|
+
name = "private-network-worker"
|
|
271
|
+
main = "src/index.ts"
|
|
272
|
+
compatibility_date = "2024-01-01"
|
|
273
|
+
|
|
274
|
+
# No special configuration needed - TCP sockets are available by default
|
|
275
|
+
# in Workers runtime
|
|
276
|
+
|
|
277
|
+
[env.production]
|
|
278
|
+
routes = [
|
|
279
|
+
{ pattern = "api.example.com/*", zone_name = "example.com" }
|
|
280
|
+
]
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Environment Variables for Endpoints
|
|
284
|
+
|
|
285
|
+
```toml
|
|
286
|
+
[vars]
|
|
287
|
+
DB_HOST = "10.0.1.50"
|
|
288
|
+
DB_PORT = "5432"
|
|
289
|
+
API_HOST = "internal-api.private.net"
|
|
290
|
+
API_PORT = "8080"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
interface Env {
|
|
295
|
+
DB_HOST: string;
|
|
296
|
+
DB_PORT: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export default {
|
|
300
|
+
async fetch(req: Request, env: Env) {
|
|
301
|
+
const socket = connect({
|
|
302
|
+
hostname: env.DB_HOST,
|
|
303
|
+
port: parseInt(env.DB_PORT)
|
|
304
|
+
});
|
|
305
|
+
// ...
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Smart Placement
|
|
311
|
+
|
|
312
|
+
Auto-locate Workers near backend services:
|
|
313
|
+
|
|
314
|
+
```toml
|
|
315
|
+
# wrangler.toml
|
|
316
|
+
[placement]
|
|
317
|
+
mode = "smart"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
export default {
|
|
322
|
+
async fetch(req: Request, env: Env, ctx: ExecutionContext) {
|
|
323
|
+
// Worker automatically runs closest to your backend
|
|
324
|
+
const socket = connect({ hostname: "backend.internal", port: 8080 });
|
|
325
|
+
// Minimized latency to private network
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Hyperdrive for Databases
|
|
331
|
+
|
|
332
|
+
For PostgreSQL/MySQL, use Hyperdrive instead of raw TCP sockets:
|
|
333
|
+
|
|
334
|
+
```toml
|
|
335
|
+
# wrangler.toml
|
|
336
|
+
[[hyperdrive]]
|
|
337
|
+
binding = "DB"
|
|
338
|
+
id = "<HYPERDRIVE_ID>"
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { Client } from 'pg';
|
|
343
|
+
|
|
344
|
+
interface Env {
|
|
345
|
+
DB: Hyperdrive;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export default {
|
|
349
|
+
async fetch(req: Request, env: Env) {
|
|
350
|
+
const client = new Client({
|
|
351
|
+
connectionString: env.DB.connectionString
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
await client.connect();
|
|
355
|
+
const result = await client.query('SELECT * FROM users');
|
|
356
|
+
await client.end();
|
|
357
|
+
|
|
358
|
+
return Response.json(result.rows);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Limits and Considerations
|
|
364
|
+
|
|
365
|
+
### TCP Socket Limits
|
|
366
|
+
|
|
367
|
+
- **Max simultaneous connections:** 6 per Worker execution
|
|
368
|
+
- **Blocked destinations:**
|
|
369
|
+
- Cloudflare IPs
|
|
370
|
+
- `localhost` / `127.0.0.1`
|
|
371
|
+
- Port 25 (SMTP - use Email Workers instead)
|
|
372
|
+
- Cannot connect back to the calling Worker (loop detection)
|
|
373
|
+
- **Scope:** Sockets must be created in handlers (fetch/scheduled/queue), not global scope
|
|
374
|
+
|
|
375
|
+
### Performance
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// ❌ BAD: Creating socket in global scope
|
|
379
|
+
// import { connect } from 'cloudflare:sockets';
|
|
380
|
+
// const globalSocket = connect({ hostname: "db", port: 5432 }); // ERROR
|
|
381
|
+
|
|
382
|
+
// ✅ GOOD: Create in handler
|
|
383
|
+
export default {
|
|
384
|
+
async fetch(req: Request) {
|
|
385
|
+
const socket = connect({ hostname: "db", port: 5432 });
|
|
386
|
+
// Use socket
|
|
387
|
+
await socket.close();
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Security
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// Validate destinations
|
|
396
|
+
function isAllowedHost(hostname: string): boolean {
|
|
397
|
+
const allowed = [
|
|
398
|
+
'internal-db.company.com',
|
|
399
|
+
'api.private.net',
|
|
400
|
+
/^10\.0\.1\.\d+$/ // Private subnet regex
|
|
401
|
+
];
|
|
402
|
+
|
|
403
|
+
return allowed.some(pattern =>
|
|
404
|
+
pattern instanceof RegExp
|
|
405
|
+
? pattern.test(hostname)
|
|
406
|
+
: pattern === hostname
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export default {
|
|
411
|
+
async fetch(req: Request) {
|
|
412
|
+
const url = new URL(req.url);
|
|
413
|
+
const target = url.searchParams.get('target');
|
|
414
|
+
|
|
415
|
+
if (!target || !isAllowedHost(target)) {
|
|
416
|
+
return new Response('Forbidden', { status: 403 });
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const socket = connect({ hostname: target, port: 443 });
|
|
420
|
+
// ...
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Common Errors
|
|
426
|
+
|
|
427
|
+
### `proxy request failed, cannot connect to the specified address`
|
|
428
|
+
|
|
429
|
+
**Cause:** Attempting to connect to disallowed address (Cloudflare IPs, localhost, blocked IPs)
|
|
430
|
+
|
|
431
|
+
**Solution:** Use public internet addresses or properly configured Tunnel endpoints
|
|
432
|
+
|
|
433
|
+
### `TCP Loop detected`
|
|
434
|
+
|
|
435
|
+
**Cause:** Worker connecting back to itself
|
|
436
|
+
|
|
437
|
+
**Solution:** Ensure destination is external service, not the Worker's own URL
|
|
438
|
+
|
|
439
|
+
### `Connections to port 25 are prohibited`
|
|
440
|
+
|
|
441
|
+
**Cause:** Attempting SMTP on port 25
|
|
442
|
+
|
|
443
|
+
**Solution:** Use [Email Workers](https://developers.cloudflare.com/email-routing/email-workers/)
|
|
444
|
+
|
|
445
|
+
### `socket is not open`
|
|
446
|
+
|
|
447
|
+
**Cause:** Trying to read/write after socket closed
|
|
448
|
+
|
|
449
|
+
**Solution:** Check socket state, use try/finally with close()
|
|
450
|
+
|
|
451
|
+
## Testing
|
|
452
|
+
|
|
453
|
+
### Local Development with Wrangler
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
wrangler dev
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Test TCP Connection
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
// test.ts
|
|
463
|
+
import { connect } from 'cloudflare:sockets';
|
|
464
|
+
|
|
465
|
+
export default {
|
|
466
|
+
async fetch(req: Request) {
|
|
467
|
+
const socket = connect({ hostname: "google.com", port: 80 });
|
|
468
|
+
|
|
469
|
+
const writer = socket.writable.getWriter();
|
|
470
|
+
await writer.write(
|
|
471
|
+
new TextEncoder().encode("GET / HTTP/1.0\r\n\r\n")
|
|
472
|
+
);
|
|
473
|
+
await writer.close();
|
|
474
|
+
|
|
475
|
+
return new Response(socket.readable, {
|
|
476
|
+
headers: { "Content-Type": "text/plain" }
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Best Practices
|
|
483
|
+
|
|
484
|
+
1. **Always close sockets:**
|
|
485
|
+
```typescript
|
|
486
|
+
const socket = connect(...);
|
|
487
|
+
try {
|
|
488
|
+
// Use socket
|
|
489
|
+
} finally {
|
|
490
|
+
await socket.close();
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
2. **Use Hyperdrive for databases** - Better performance, connection pooling
|
|
495
|
+
|
|
496
|
+
3. **Validate destinations** - Prevent connections to unintended hosts
|
|
497
|
+
|
|
498
|
+
4. **Handle errors gracefully:**
|
|
499
|
+
```typescript
|
|
500
|
+
try {
|
|
501
|
+
const socket = connect(...);
|
|
502
|
+
await socket.opened;
|
|
503
|
+
// Use socket
|
|
504
|
+
} catch (error) {
|
|
505
|
+
console.error('Socket error:', error);
|
|
506
|
+
return new Response('Service unavailable', { status: 503 });
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
5. **Use Smart Placement** for latency-sensitive applications
|
|
511
|
+
|
|
512
|
+
6. **Prefer fetch() for HTTP** - Use TCP sockets only when necessary
|
|
513
|
+
|
|
514
|
+
## Real-World Patterns
|
|
515
|
+
|
|
516
|
+
### Multi-Protocol Gateway
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
import { connect } from 'cloudflare:sockets';
|
|
520
|
+
|
|
521
|
+
interface Protocol {
|
|
522
|
+
connect(host: string, port: number): Promise<string>;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
class SSHProtocol implements Protocol {
|
|
526
|
+
async connect(host: string, port: number): Promise<string> {
|
|
527
|
+
const socket = connect({ hostname: host, port }, { secureTransport: "on" });
|
|
528
|
+
// SSH implementation
|
|
529
|
+
await socket.close();
|
|
530
|
+
return "SSH connection established";
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
class PostgresProtocol implements Protocol {
|
|
535
|
+
async connect(host: string, port: number): Promise<string> {
|
|
536
|
+
const socket = connect(
|
|
537
|
+
{ hostname: host, port },
|
|
538
|
+
{ secureTransport: "starttls" }
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
// Postgres wire protocol
|
|
542
|
+
const secureSocket = socket.startTls();
|
|
543
|
+
await secureSocket.close();
|
|
544
|
+
return "Postgres connection established";
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export default {
|
|
549
|
+
async fetch(req: Request) {
|
|
550
|
+
const url = new URL(req.url);
|
|
551
|
+
const protocol = url.pathname.slice(1); // /ssh or /postgres
|
|
552
|
+
|
|
553
|
+
const protocols: Record<string, Protocol> = {
|
|
554
|
+
ssh: new SSHProtocol(),
|
|
555
|
+
postgres: new PostgresProtocol()
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
const handler = protocols[protocol];
|
|
559
|
+
if (!handler) {
|
|
560
|
+
return new Response('Unknown protocol', { status: 400 });
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const result = await handler.connect('internal.net', 22);
|
|
564
|
+
return new Response(result);
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Reference
|
|
570
|
+
|
|
571
|
+
- [TCP Sockets Documentation](https://developers.cloudflare.com/workers/runtime-apis/tcp-sockets/)
|
|
572
|
+
- [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)
|
|
573
|
+
- [Hyperdrive](https://developers.cloudflare.com/hyperdrive/)
|
|
574
|
+
- [Smart Placement](https://developers.cloudflare.com/workers/configuration/smart-placement/)
|
|
575
|
+
- [Email Workers](https://developers.cloudflare.com/email-routing/email-workers/)
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
This skill focuses exclusively on connecting Workers to private networks and VPCs. For general Workers development, see the `cloudflare-workers` skill.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Cloudflare Workflows
|
|
2
|
+
|
|
3
|
+
Durable multi-step applications with automatic retries, state persistence, and long-running execution.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- Chain steps with automatic retry logic
|
|
8
|
+
- Persist state between steps (minutes → weeks)
|
|
9
|
+
- Handle failures without losing progress
|
|
10
|
+
- Wait for external events/approvals
|
|
11
|
+
- Sleep without consuming resources
|
|
12
|
+
|
|
13
|
+
**Available:** Free & Paid Workers plans
|
|
14
|
+
|
|
15
|
+
## Core Concepts
|
|
16
|
+
|
|
17
|
+
**Workflow**: Class extending `WorkflowEntrypoint` with `run` method
|
|
18
|
+
**Instance**: Single execution with unique ID & independent state
|
|
19
|
+
**Steps**: Independently retriable units via `step.do()` - API calls, DB queries, AI invocations
|
|
20
|
+
**State**: Persisted from step returns; step name = cache key
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
|
|
26
|
+
|
|
27
|
+
type Env = { MY_WORKFLOW: Workflow; DB: D1Database };
|
|
28
|
+
type Params = { userId: string };
|
|
29
|
+
|
|
30
|
+
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
31
|
+
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
|
|
32
|
+
const user = await step.do('fetch user', async () => {
|
|
33
|
+
return await this.env.DB.prepare('SELECT * FROM users WHERE id = ?')
|
|
34
|
+
.bind(event.payload.userId).first();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await step.sleep('wait 7 days', '7 days');
|
|
38
|
+
|
|
39
|
+
await step.do('send reminder', async () => {
|
|
40
|
+
await sendEmail(user.email, 'Reminder!');
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Key Features
|
|
47
|
+
|
|
48
|
+
- **Durability**: Failed steps don't re-run successful ones
|
|
49
|
+
- **Retries**: Configurable backoff (constant/linear/exponential)
|
|
50
|
+
- **Events**: `waitForEvent()` for webhooks/approvals (timeout: 1h → 365d)
|
|
51
|
+
- **Sleep**: `sleep()` / `sleepUntil()` for scheduling (max 365d)
|
|
52
|
+
- **Parallel**: `Promise.all()` for concurrent steps
|
|
53
|
+
- **Idempotency**: Check-then-execute patterns
|
|
54
|
+
|
|
55
|
+
## Further Reading
|
|
56
|
+
|
|
57
|
+
- [configuration.md](./configuration.md) - wrangler.toml, step config
|
|
58
|
+
- [api.md](./api.md) - Step APIs, instance management
|
|
59
|
+
- [patterns.md](./patterns.md) - Common workflows, orchestration
|
|
60
|
+
- [gotchas.md](./gotchas.md) - Timeouts, limits, debugging
|
|
61
|
+
|
|
62
|
+
[Official Docs](https://developers.cloudflare.com/workflows/)
|