opencodekit 0.15.4 → 0.15.6
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 +2 -2
- package/dist/template/.opencode/agent/explore.md +13 -12
- package/dist/template/.opencode/command/cloudflare.md +70 -0
- package/dist/template/.opencode/memory/observations/2026-01-19-learning-oh-my-opencode-slim-vs-opencodekit-templ.md +27 -0
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/plugin/sessions.ts +38 -4
- 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/dist/template/.opencode/tool/memory-read.ts +64 -44
- package/dist/template/.opencode/tool/memory-search.ts +9 -2
- package/dist/template/.opencode/tool/memory-update.ts +59 -47
- package/dist/template/.opencode/tool/observation.ts +16 -2
- package/package.json +1 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Durable Objects Patterns
|
|
2
|
+
|
|
3
|
+
## Parent-Child Relationships
|
|
4
|
+
|
|
5
|
+
Don't put all data in a single DO. For hierarchical data (workspaces → projects, game servers → matches), create separate child DOs. Parent coordinates and tracks children; children handle own state independently.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
export class GameServer extends DurableObject<Env> {
|
|
9
|
+
async createMatch(matchId: string): Promise<string> {
|
|
10
|
+
// Store child reference in parent
|
|
11
|
+
this.ctx.storage.sql.exec(
|
|
12
|
+
"INSERT INTO matches (id, created_at, status) VALUES (?, ?, ?)",
|
|
13
|
+
matchId, Date.now(), "active"
|
|
14
|
+
);
|
|
15
|
+
return matchId;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async routeToMatch(matchId: string, playerId: string, action: string) {
|
|
19
|
+
// Route to child DO - operations on different children run in parallel
|
|
20
|
+
const childId = this.env.MATCH.idFromName(matchId);
|
|
21
|
+
const child = this.env.MATCH.get(childId);
|
|
22
|
+
return await child.handleAction(playerId, action);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async listMatches(): Promise<string[]> {
|
|
26
|
+
// Query parent only - children stay hibernated
|
|
27
|
+
return this.ctx.storage.sql
|
|
28
|
+
.exec<{ id: string }>("SELECT id FROM matches WHERE status = ?", "active")
|
|
29
|
+
.toArray()
|
|
30
|
+
.map(r => r.id);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Benefits: parallelism across children, each child has own SQLite database, listing doesn't wake children.
|
|
36
|
+
|
|
37
|
+
## Fleet Pattern (Hierarchical DOs)
|
|
38
|
+
|
|
39
|
+
URL-based hierarchy creates infinite nesting of manager/agent relationships. Each path segment (`/team/project/task`) maps to a unique DO via `idFromName()`.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// Worker: Route all requests based on URL path
|
|
43
|
+
app.all('*', async (c) => {
|
|
44
|
+
const path = new URL(c.req.url).pathname;
|
|
45
|
+
const parts = path.split('/').filter(Boolean);
|
|
46
|
+
const doName = parts.length === 0 ? '/' : `/${parts.join('/')}`;
|
|
47
|
+
|
|
48
|
+
const id = c.env.FLEET_DO.idFromName(doName);
|
|
49
|
+
return c.env.FLEET_DO.get(id).fetch(c.req.raw);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Single unified DO class handles both manager and agent roles
|
|
53
|
+
export class FleetDO extends DurableObject<Env> {
|
|
54
|
+
async deleteWithCascade() {
|
|
55
|
+
const data = await this.ctx.storage.get<{ agents: string[] }>('data');
|
|
56
|
+
const myPath = /* derive from context */;
|
|
57
|
+
|
|
58
|
+
// Cascade delete to all children
|
|
59
|
+
for (const agent of data?.agents || []) {
|
|
60
|
+
const childPath = myPath === '/' ? `/${agent}` : `${myPath}/${agent}`;
|
|
61
|
+
const child = this.env.FLEET_DO.get(this.env.FLEET_DO.idFromName(childPath));
|
|
62
|
+
await child.fetch(new Request('https://internal' + childPath, { method: 'DELETE' }));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
await this.ctx.storage.deleteAll();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use cases: collaborative IDEs (file per DO), distributed task runners, IoT device management, game server infrastructure.
|
|
71
|
+
|
|
72
|
+
## Per-User DO Pattern
|
|
73
|
+
|
|
74
|
+
One DO per user for settings, presence, inbox, profile data. Deterministic routing via `idFromName(userId)`.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
export class UserDO extends DurableObject<Env> {
|
|
78
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
79
|
+
super(ctx, env);
|
|
80
|
+
ctx.blockConcurrencyWhile(async () => {
|
|
81
|
+
this.ctx.storage.sql.exec(`
|
|
82
|
+
CREATE TABLE IF NOT EXISTS profile (key TEXT PRIMARY KEY, value TEXT);
|
|
83
|
+
CREATE TABLE IF NOT EXISTS inbox (id TEXT PRIMARY KEY, data TEXT, created_at INTEGER);
|
|
84
|
+
`);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async getProfile(): Promise<Record<string, string>> {
|
|
89
|
+
return Object.fromEntries(
|
|
90
|
+
this.ctx.storage.sql.exec<{ key: string; value: string }>("SELECT * FROM profile").toArray()
|
|
91
|
+
.map(r => [r.key, r.value])
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async updateProfile(updates: Record<string, string>) {
|
|
96
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
97
|
+
this.ctx.storage.sql.exec(
|
|
98
|
+
"INSERT OR REPLACE INTO profile (key, value) VALUES (?, ?)", key, value
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
this.broadcast({ type: 'profile_updated', data: updates });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private broadcast(msg: object) {
|
|
105
|
+
const payload = JSON.stringify(msg);
|
|
106
|
+
for (const ws of this.ctx.getWebSockets()) ws.send(payload);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Worker
|
|
111
|
+
const id = env.USER_DO.idFromName(userId); // deterministic per-user routing
|
|
112
|
+
const user = env.USER_DO.get(id);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Benefits: natural ownership boundary, hibernates between user activity, WebSocket for real-time updates.
|
|
116
|
+
|
|
117
|
+
## Colo-Aware Sharding
|
|
118
|
+
|
|
119
|
+
Use `request.cf.colo` for geographic distribution. Rate limit per-colo before hitting DO.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
export default {
|
|
123
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
124
|
+
const userId = new URL(request.url).searchParams.get("userId") || "unknown";
|
|
125
|
+
const colo = request.cf?.colo || "unknown";
|
|
126
|
+
const shardKey = `${colo}:${userId}`;
|
|
127
|
+
|
|
128
|
+
// Rate limit per-colo (counters not shared across datacenters)
|
|
129
|
+
const { success } = await env.RATE_LIMITER.limit({ key: shardKey });
|
|
130
|
+
if (!success) return new Response("Rate limited", { status: 429 });
|
|
131
|
+
|
|
132
|
+
// Route to colo-aware DO shard
|
|
133
|
+
const stub = env.MY_DO.get(env.MY_DO.idFromName(shardKey));
|
|
134
|
+
return await stub.fetch(request);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`request.cf.colo` returns IATA airport code (e.g., "SFO", "LHR"). Useful for high-throughput systems needing geographic awareness.
|
|
140
|
+
|
|
141
|
+
## Rate Limiting
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
async checkLimit(key: string, limit: number, windowMs: number): Promise<boolean> {
|
|
145
|
+
const req = await this.ctx.storage.sql.exec(
|
|
146
|
+
"SELECT COUNT(*) as count FROM requests WHERE key = ? AND timestamp > ?",
|
|
147
|
+
key, Date.now() - windowMs
|
|
148
|
+
).one();
|
|
149
|
+
if (req.count >= limit) return false;
|
|
150
|
+
this.ctx.storage.sql.exec("INSERT INTO requests (key, timestamp) VALUES (?, ?)", key, Date.now());
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Distributed Lock
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
private held = false;
|
|
159
|
+
async acquire(timeoutMs = 5000): Promise<boolean> {
|
|
160
|
+
if (this.held) return false;
|
|
161
|
+
this.held = true;
|
|
162
|
+
await this.ctx.storage.setAlarm(Date.now() + timeoutMs);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
async release() { this.held = false; await this.ctx.storage.deleteAlarm(); }
|
|
166
|
+
async alarm() { this.held = false; }
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Real-time Collaboration
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
async fetch(req: Request): Promise<Response> {
|
|
173
|
+
const [client, server] = Object.values(new WebSocketPair());
|
|
174
|
+
this.ctx.acceptWebSocket(server);
|
|
175
|
+
server.send(JSON.stringify({ type: "init", content: this.ctx.storage.kv.get("doc") || "" }));
|
|
176
|
+
return new Response(null, { status: 101, webSocket: client });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async webSocketMessage(ws: WebSocket, msg: string) {
|
|
180
|
+
const data = JSON.parse(msg);
|
|
181
|
+
if (data.type === "edit") {
|
|
182
|
+
this.ctx.storage.kv.put("doc", data.content);
|
|
183
|
+
for (const c of this.ctx.getWebSockets()) if (c !== ws) c.send(msg);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Session Management
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
async createSession(userId: string, data: object): Promise<string> {
|
|
192
|
+
const id = crypto.randomUUID(), exp = Date.now() + 86400000;
|
|
193
|
+
this.ctx.storage.sql.exec("INSERT INTO sessions VALUES (?, ?, ?, ?)", id, userId, JSON.stringify(data), exp);
|
|
194
|
+
await this.ctx.storage.setAlarm(exp);
|
|
195
|
+
return id;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async getSession(id: string): Promise<object | null> {
|
|
199
|
+
const row = this.ctx.storage.sql.exec("SELECT data FROM sessions WHERE id = ? AND expires_at > ?", id, Date.now()).one();
|
|
200
|
+
return row ? JSON.parse(row.data) : null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async alarm() { this.ctx.storage.sql.exec("DELETE FROM sessions WHERE expires_at <= ?", Date.now()); }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Deduplication
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
private pending = new Map<string, Promise<Response>>();
|
|
210
|
+
async deduplicatedFetch(url: string): Promise<Response> {
|
|
211
|
+
if (this.pending.has(url)) return this.pending.get(url)!;
|
|
212
|
+
const p = fetch(url).finally(() => this.pending.delete(url));
|
|
213
|
+
this.pending.set(url, p);
|
|
214
|
+
return p;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Multiple Events (Single Alarm)
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
async scheduleEvent(id: string, runAt: number, repeatMs?: number) {
|
|
222
|
+
await this.ctx.storage.put(`event:${id}`, { id, runAt, repeatMs });
|
|
223
|
+
const curr = await this.ctx.storage.getAlarm();
|
|
224
|
+
if (!curr || runAt < curr) await this.ctx.storage.setAlarm(runAt);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async alarm() {
|
|
228
|
+
const now = Date.now(), events = await this.ctx.storage.list({ prefix: "event:" });
|
|
229
|
+
let next: number | null = null;
|
|
230
|
+
for (const [key, ev] of events) {
|
|
231
|
+
if (ev.runAt <= now) {
|
|
232
|
+
await this.processEvent(ev);
|
|
233
|
+
ev.repeatMs ? await this.ctx.storage.put(key, { ...ev, runAt: now + ev.repeatMs }) : await this.ctx.storage.delete(key);
|
|
234
|
+
}
|
|
235
|
+
if (ev.runAt > now && (!next || ev.runAt < next)) next = ev.runAt;
|
|
236
|
+
}
|
|
237
|
+
if (next) await this.ctx.storage.setAlarm(next);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Best Practices
|
|
242
|
+
|
|
243
|
+
**Design for Hibernation**: DOs should sleep by default, wake for meaningful work, then sleep again. All important state must persist to storage—in-memory state is lost on eviction. Use `blockConcurrencyWhile()` in constructor to reload state on wake. Design so any instance could disappear and reconstruct from storage.
|
|
244
|
+
|
|
245
|
+
**Atom of Coordination**: Each DO should own ONE logical unit (user, room, document, session). If data spans multiple boundaries or doesn't have natural ownership, DO may be wrong choice.
|
|
246
|
+
|
|
247
|
+
**Design**: Keep objects focused, use `idFromName()` for coordination, `newUniqueId()` for sharding, minimize constructor work, leverage WebSocket hibernation
|
|
248
|
+
|
|
249
|
+
**Storage**: Prefer SQLite, create indexes judiciously, batch with transactions, set alarms for cleanup, use PITR before risky ops
|
|
250
|
+
|
|
251
|
+
**Performance**: One DO ~1000 req/s max - shard for more, cache in memory, avoid long ops, use alarms for deferred work
|
|
252
|
+
|
|
253
|
+
**Reliability**: Handle 503 with retry+backoff, design for cold starts, test migrations, monitor alarm retries
|
|
254
|
+
|
|
255
|
+
**Security**: Validate inputs in Workers, don't trust user names, rate limit DO creation, use jurisdiction tags, encrypt sensitive data
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Cloudflare Email Routing Skill Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Cloudflare Email Routing enables custom email addresses for your domain that route to verified destination addresses. It's free, privacy-focused (no storage/access), and includes Email Workers for programmatic email processing.
|
|
6
|
+
|
|
7
|
+
**Available to all Cloudflare customers using Cloudflare a...
|
|
8
|
+
|
|
9
|
+
## In This Reference
|
|
10
|
+
|
|
11
|
+
- **[configuration.md](./configuration.md)** - Setup, deployment, configuration
|
|
12
|
+
- **[api.md](./api.md)** - API endpoints, methods, interfaces
|
|
13
|
+
- **[patterns.md](./patterns.md)** - Common patterns, use cases, examples
|
|
14
|
+
- **[gotchas.md](./gotchas.md)** - Troubleshooting, best practices, limitations
|
|
15
|
+
|
|
16
|
+
## See Also
|
|
17
|
+
|
|
18
|
+
- [Cloudflare Docs](https://developers.cloudflare.com/)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
## REST API Operations
|
|
2
|
+
|
|
3
|
+
### Authentication
|
|
4
|
+
|
|
5
|
+
Use API tokens (preferred) or API keys:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# API Token (recommended)
|
|
9
|
+
curl -H "Authorization: Bearer $API_TOKEN" \
|
|
10
|
+
https://api.cloudflare.com/client/v4/...
|
|
11
|
+
|
|
12
|
+
# API Key (legacy)
|
|
13
|
+
curl -H "X-Auth-Email: $EMAIL" \
|
|
14
|
+
-H "X-Auth-Key: $API_KEY" \
|
|
15
|
+
https://api.cloudflare.com/client/v4/...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Enable Email Routing
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
POST /zones/{zone_id}/email/routing/dns
|
|
22
|
+
|
|
23
|
+
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/dns" \
|
|
24
|
+
-H "Authorization: Bearer $API_TOKEN" \
|
|
25
|
+
-H "Content-Type: application/json"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Disable Email Routing
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
DELETE /zones/{zone_id}/email/routing/dns
|
|
32
|
+
|
|
33
|
+
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/dns" \
|
|
34
|
+
-H "Authorization: Bearer $API_TOKEN"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Get Email Routing Settings
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
GET /zones/{zone_id}/email/routing
|
|
41
|
+
|
|
42
|
+
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing" \
|
|
43
|
+
-H "Authorization: Bearer $API_TOKEN"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Resp
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
## Wrangler Configuration
|
|
2
|
+
|
|
3
|
+
### Basic Email Worker
|
|
4
|
+
|
|
5
|
+
```toml
|
|
6
|
+
name = "email-worker"
|
|
7
|
+
main = "src/index.ts"
|
|
8
|
+
compatibility_date = "2024-01-01"
|
|
9
|
+
|
|
10
|
+
[[send_email]]
|
|
11
|
+
name = "EMAIL"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or in JSON:
|
|
15
|
+
|
|
16
|
+
```jsonc
|
|
17
|
+
{
|
|
18
|
+
"name": "email-worker",
|
|
19
|
+
"main": "src/index.ts",
|
|
20
|
+
"compatibility_date": "2024-01-01",
|
|
21
|
+
"send_email": [
|
|
22
|
+
{
|
|
23
|
+
"name": "EMAIL"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### With KV/R2 Bindings
|
|
30
|
+
|
|
31
|
+
```toml
|
|
32
|
+
name = "email-processor"
|
|
33
|
+
main = "src/index.ts"
|
|
34
|
+
|
|
35
|
+
[[send_email]]
|
|
36
|
+
name = "EMAIL"
|
|
37
|
+
|
|
38
|
+
[[kv_namespaces]]
|
|
39
|
+
binding = "EMAIL_METADATA"
|
|
40
|
+
id = "your-kv-namespace-id"
|
|
41
|
+
|
|
42
|
+
[[r2_buckets]]
|
|
43
|
+
binding = "EMAIL_BUCKET"
|
|
44
|
+
bucket_name = "email-archive"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Local Development
|
|
48
|
+
|
|
49
|
+
Run locally with `wrangler dev`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx wrangler dev
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Test receiving email via curl:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
curl --request POST 'http://localhost:8787/cdn-cgi/handler/email' \
|
|
59
|
+
--url-query 'from=sender@example.com' \
|
|
60
|
+
--url-query 'to=recipient@example.com' \
|
|
61
|
+
--header 'Content-Type: application/json' \
|
|
62
|
+
--data-raw 'From: sender@example.com
|
|
63
|
+
To: recipient@example.co
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## Best Practices
|
|
2
|
+
|
|
3
|
+
1. **Verify destinations first**: Rules auto-disabled until destination verified
|
|
4
|
+
2. **Use Email Workers for complex logic**: Don't create dozens of rules; use Workers
|
|
5
|
+
3. **Monitor spam scores**: Check `X-Cf-Spamh-Score` header for filtering
|
|
6
|
+
4. **Handle auth failures**: Enforce SPF/DKIM/DMARC at sender domain
|
|
7
|
+
5. **Use subaddressing strategically**: Track where emails come from (`user+service@`)
|
|
8
|
+
6. **Consider Worker limits**: Upgrade to Paid plan for heavy processing
|
|
9
|
+
7. **Store raw emails carefully**: R2 for archival, KV for metadata
|
|
10
|
+
8. **Implement proper error handling**: Always handle `setReject` cases
|
|
11
|
+
9. **Test locally with wrangler dev**: Use curl to simulate email delivery
|
|
12
|
+
10. **Use priority for rule ordering**: Lower priority = evaluated first
|
|
13
|
+
|
|
14
|
+
## Debugging
|
|
15
|
+
|
|
16
|
+
### Chec
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
## Common Patterns
|
|
2
|
+
|
|
3
|
+
### 1. Allowlist Email Worker
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
export default {
|
|
7
|
+
async email(message, env, ctx) {
|
|
8
|
+
const allowList = ["friend@example.com", "coworker@example.com"];
|
|
9
|
+
if (allowList.indexOf(message.from) == -1) {
|
|
10
|
+
message.setReject("Address not allowed");
|
|
11
|
+
} else {
|
|
12
|
+
await message.forward("inbox@corp");
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 2. Parse Email with postal-mime
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import * as PostalMime from 'postal-mime';
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
async email(message, env, ctx) {
|
|
25
|
+
const parser = new PostalMime.default();
|
|
26
|
+
const rawEmail = new Response(message.raw);
|
|
27
|
+
const email = await parser.parse(await rawEmail.arrayBuffer());
|
|
28
|
+
|
|
29
|
+
console.log({
|
|
30
|
+
from: email.from,
|
|
31
|
+
to: email.to,
|
|
32
|
+
subject: email.subject,
|
|
33
|
+
html: email.html,
|
|
34
|
+
attachments: email.attachments
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await message.forward("destination@example.com");
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Forward with Custom Headers
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
export default {
|
|
46
|
+
async email(message, env,
|