opencodekit 0.15.3 → 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/AGENTS.md +209 -77
- package/dist/template/.opencode/agent/plan.md +4 -0
- 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,198 @@
|
|
|
1
|
+
# Cron Triggers API
|
|
2
|
+
|
|
3
|
+
## Basic Handler
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
interface Env {
|
|
7
|
+
// Bindings (KV, R2, D1, secrets, etc.)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
async scheduled(
|
|
12
|
+
controller: ScheduledController,
|
|
13
|
+
env: Env,
|
|
14
|
+
ctx: ExecutionContext,
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
console.log("Cron executed:", new Date(controller.scheduledTime));
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
export default {
|
|
23
|
+
async scheduled(controller, env, ctx) {
|
|
24
|
+
console.log("Cron executed:", new Date(controller.scheduledTime));
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from workers import WorkerEntrypoint
|
|
31
|
+
|
|
32
|
+
class Default(WorkerEntrypoint):
|
|
33
|
+
async def scheduled(self, controller, env, ctx):
|
|
34
|
+
print(f"Cron executed: {controller.scheduledTime}")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## ScheduledController
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
interface ScheduledController {
|
|
41
|
+
scheduledTime: number; // Unix ms when scheduled to run
|
|
42
|
+
cron: string; // Expression that triggered (e.g., "*/5 * * * *")
|
|
43
|
+
type: string; // Always "scheduled"
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Parse time:**
|
|
48
|
+
```typescript
|
|
49
|
+
const date = new Date(controller.scheduledTime);
|
|
50
|
+
console.log(date.toISOString());
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Handler Parameters
|
|
54
|
+
|
|
55
|
+
**`controller: ScheduledController`**
|
|
56
|
+
- Access cron expression and scheduled time
|
|
57
|
+
|
|
58
|
+
**`env: Env`**
|
|
59
|
+
- All bindings: KV, R2, D1, secrets, service bindings
|
|
60
|
+
|
|
61
|
+
**`ctx: ExecutionContext`**
|
|
62
|
+
- `ctx.waitUntil(promise)` - Extend execution for async tasks (logging, cleanup, external APIs)
|
|
63
|
+
- First `waitUntil` failure recorded in Cron Events
|
|
64
|
+
|
|
65
|
+
## Multiple Schedules Pattern
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { Hono } from "hono";
|
|
69
|
+
|
|
70
|
+
interface Env {
|
|
71
|
+
MY_KV: KVNamespace;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const app = new Hono<{ Bindings: Env }>();
|
|
75
|
+
app.get("/", (c) => c.text("API Running"));
|
|
76
|
+
|
|
77
|
+
export default {
|
|
78
|
+
fetch: app.fetch,
|
|
79
|
+
|
|
80
|
+
async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext) {
|
|
81
|
+
switch (controller.cron) {
|
|
82
|
+
case "*/3 * * * *":
|
|
83
|
+
ctx.waitUntil(updateRecentData(env));
|
|
84
|
+
break;
|
|
85
|
+
|
|
86
|
+
case "0 * * * *":
|
|
87
|
+
ctx.waitUntil(processHourlyAggregation(env));
|
|
88
|
+
break;
|
|
89
|
+
|
|
90
|
+
case "0 2 * * *":
|
|
91
|
+
ctx.waitUntil(performDailyMaintenance(env));
|
|
92
|
+
break;
|
|
93
|
+
|
|
94
|
+
default:
|
|
95
|
+
console.warn(`Unhandled cron: ${controller.cron}`);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## ctx.waitUntil Usage
|
|
102
|
+
|
|
103
|
+
Non-blocking async tasks:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
export default {
|
|
107
|
+
async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext) {
|
|
108
|
+
// Critical path - runs immediately
|
|
109
|
+
const data = await fetchCriticalData();
|
|
110
|
+
|
|
111
|
+
// Non-blocking background tasks
|
|
112
|
+
ctx.waitUntil(
|
|
113
|
+
Promise.all([
|
|
114
|
+
logToAnalytics(data),
|
|
115
|
+
cleanupOldRecords(env.DB),
|
|
116
|
+
notifyWebhook(env.WEBHOOK_URL, data),
|
|
117
|
+
])
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// Handler returns while waitUntil tasks complete
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Workflow Integration
|
|
126
|
+
|
|
127
|
+
Trigger long-running workflows on schedule:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { WorkflowEntrypoint } from "cloudflare:workers";
|
|
131
|
+
|
|
132
|
+
interface Env {
|
|
133
|
+
MY_WORKFLOW: Workflow;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export class DataProcessingWorkflow extends WorkflowEntrypoint {
|
|
137
|
+
async run(event: any, step: any) {
|
|
138
|
+
const data = await step.do("fetch-data", async () => {
|
|
139
|
+
return await fetchLargeDataset();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const processed = await step.do("process-data", async () => {
|
|
143
|
+
return await processDataset(data);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await step.do("store-results", async () => {
|
|
147
|
+
return await storeResults(processed);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export default {
|
|
153
|
+
async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext) {
|
|
154
|
+
const instance = await env.MY_WORKFLOW.create({
|
|
155
|
+
params: {
|
|
156
|
+
scheduledTime: controller.scheduledTime,
|
|
157
|
+
cron: controller.cron,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
console.log(`Started workflow: ${instance.id}`);
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Testing Handler
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// test/scheduled.test.ts
|
|
170
|
+
import { describe, it, expect } from "vitest";
|
|
171
|
+
import worker from "../src/index";
|
|
172
|
+
|
|
173
|
+
describe("Scheduled Handler", () => {
|
|
174
|
+
it("processes scheduled event", async () => {
|
|
175
|
+
const env = getMiniflareBindings();
|
|
176
|
+
const ctx = {
|
|
177
|
+
waitUntil: (promise: Promise<any>) => promise,
|
|
178
|
+
passThroughOnException: () => {},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const controller = {
|
|
182
|
+
scheduledTime: Date.now(),
|
|
183
|
+
cron: "*/5 * * * *",
|
|
184
|
+
type: "scheduled" as const,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
await worker.scheduled(controller, env, ctx);
|
|
188
|
+
|
|
189
|
+
const result = await env.MY_KV.get("last_run");
|
|
190
|
+
expect(result).toBeDefined();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## See Also
|
|
196
|
+
|
|
197
|
+
- [README.md](./README.md) - Overview
|
|
198
|
+
- [patterns.md](./patterns.md) - Use cases, examples
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Cron Triggers Configuration
|
|
2
|
+
|
|
3
|
+
## wrangler.jsonc
|
|
4
|
+
|
|
5
|
+
```jsonc
|
|
6
|
+
{
|
|
7
|
+
"$schema": "./node_modules/wrangler/config-schema.json",
|
|
8
|
+
"name": "my-cron-worker",
|
|
9
|
+
"main": "src/index.ts",
|
|
10
|
+
"compatibility_date": "2024-01-01",
|
|
11
|
+
|
|
12
|
+
"triggers": {
|
|
13
|
+
"crons": [
|
|
14
|
+
"*/5 * * * *", // Every 5 minutes
|
|
15
|
+
"0 */2 * * *", // Every 2 hours
|
|
16
|
+
"0 9 * * MON-FRI", // Weekdays at 9am UTC
|
|
17
|
+
"0 2 1 * *" // Monthly on 1st at 2am UTC
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## wrangler.toml
|
|
24
|
+
|
|
25
|
+
```toml
|
|
26
|
+
name = "my-cron-worker"
|
|
27
|
+
main = "src/index.ts"
|
|
28
|
+
compatibility_date = "2024-01-01"
|
|
29
|
+
|
|
30
|
+
[triggers]
|
|
31
|
+
crons = [
|
|
32
|
+
"*/5 * * * *", # Every 5 minutes
|
|
33
|
+
"0 */2 * * *", # Every 2 hours
|
|
34
|
+
"0 9 * * MON-FRI", # Weekdays at 9am UTC
|
|
35
|
+
"0 2 1 * *" # Monthly on 1st at 2am UTC
|
|
36
|
+
]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Environment-Specific Schedules
|
|
40
|
+
|
|
41
|
+
```jsonc
|
|
42
|
+
{
|
|
43
|
+
"name": "my-cron-worker",
|
|
44
|
+
"triggers": {
|
|
45
|
+
"crons": ["0 */6 * * *"] // Prod: every 6 hours
|
|
46
|
+
},
|
|
47
|
+
"env": {
|
|
48
|
+
"staging": {
|
|
49
|
+
"triggers": {
|
|
50
|
+
"crons": ["*/15 * * * *"] // Staging: every 15min
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"dev": {
|
|
54
|
+
"triggers": {
|
|
55
|
+
"crons": ["*/5 * * * *"] // Dev: every 5min
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```toml
|
|
63
|
+
name = "my-cron-worker"
|
|
64
|
+
|
|
65
|
+
[triggers]
|
|
66
|
+
crons = ["0 */6 * * *"] # Prod: every 6 hours
|
|
67
|
+
|
|
68
|
+
[env.staging.triggers]
|
|
69
|
+
crons = ["*/15 * * * *"] # Staging: every 15min
|
|
70
|
+
|
|
71
|
+
[env.dev.triggers]
|
|
72
|
+
crons = ["*/5 * * * *"] # Dev: every 5min
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Schedule Format
|
|
76
|
+
|
|
77
|
+
**5-field structure:**
|
|
78
|
+
```
|
|
79
|
+
minute hour day-of-month month day-of-week
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Special characters:**
|
|
83
|
+
- `*` - Any value
|
|
84
|
+
- `,` - List: `1,15,30 * * * *` (minutes 1, 15, 30)
|
|
85
|
+
- `-` - Range: `0 9-17 * * *` (9am-5pm)
|
|
86
|
+
- `/` - Step: `*/10 * * * *` (every 10 minutes)
|
|
87
|
+
- `L` - Last: `0 0 L * *` (last day of month), `0 18 * * FRI-L` (last Friday)
|
|
88
|
+
- `W` - Weekday: `0 9 15W * *` (weekday nearest 15th)
|
|
89
|
+
- `#` - Nth: `0 10 * * MON#1` (1st Monday)
|
|
90
|
+
|
|
91
|
+
## Managing Triggers
|
|
92
|
+
|
|
93
|
+
**Remove all:**
|
|
94
|
+
```jsonc
|
|
95
|
+
{
|
|
96
|
+
"triggers": {
|
|
97
|
+
"crons": [] // Empty array removes all
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Preserve existing:**
|
|
103
|
+
```jsonc
|
|
104
|
+
{
|
|
105
|
+
// Omit "triggers" entirely to keep existing crons
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Deployment
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Deploy with config crons
|
|
113
|
+
npx wrangler deploy
|
|
114
|
+
|
|
115
|
+
# Deploy specific environment
|
|
116
|
+
npx wrangler deploy --env production
|
|
117
|
+
|
|
118
|
+
# View deployments
|
|
119
|
+
npx wrangler deployments list
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**⚠️ Changes take up to 15 minutes to propagate globally**
|
|
123
|
+
|
|
124
|
+
## API Management
|
|
125
|
+
|
|
126
|
+
**Get triggers:**
|
|
127
|
+
```bash
|
|
128
|
+
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/{script_name}/schedules" \
|
|
129
|
+
-H "Authorization: Bearer {api_token}"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Update triggers:**
|
|
133
|
+
```bash
|
|
134
|
+
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/{script_name}/schedules" \
|
|
135
|
+
-H "Authorization: Bearer {api_token}" \
|
|
136
|
+
-H "Content-Type: application/json" \
|
|
137
|
+
-d '{"crons": ["*/5 * * * *", "0 2 * * *"]}'
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Delete all:**
|
|
141
|
+
```bash
|
|
142
|
+
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/{script_name}/schedules" \
|
|
143
|
+
-H "Authorization: Bearer {api_token}" \
|
|
144
|
+
-H "Content-Type: application/json" \
|
|
145
|
+
-d '{"crons": []}'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## See Also
|
|
149
|
+
|
|
150
|
+
- [README.md](./README.md) - Overview, quick start
|
|
151
|
+
- [api.md](./api.md) - Handler implementation
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Cron Triggers Gotchas
|
|
2
|
+
|
|
3
|
+
## Timezone Issues
|
|
4
|
+
|
|
5
|
+
**⚠️ UTC ONLY** - No timezone configuration
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// ❌ Wrong: "0 9 * * *" // 9am UTC, not local
|
|
9
|
+
// ✅ Right: "0 17 * * *" // 9am PST (UTC-8) = 17:00 UTC
|
|
10
|
+
// Calculate: utcHour = (localHour - utcOffset + 24) % 24
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Propagation Delay
|
|
14
|
+
|
|
15
|
+
**Changes take up to 15 minutes**. Verify: Dashboard → Workers → Select Worker → Settings → Triggers
|
|
16
|
+
|
|
17
|
+
## Limits
|
|
18
|
+
|
|
19
|
+
| Plan | Triggers/Worker | CPU Time | Execution |
|
|
20
|
+
|------|----------------|----------|-----------|
|
|
21
|
+
| Free | 3 | 10ms | At-least-once |
|
|
22
|
+
| Paid | Unlimited | 50ms | At-least-once |
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// ❌ BAD: await processLargeDataset(); // May exceed CPU
|
|
26
|
+
// ✅ GOOD: ctx.waitUntil(processLargeDataset(env));
|
|
27
|
+
// ✅ OR: await env.WORKFLOW.create({});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Duplicate Executions
|
|
31
|
+
|
|
32
|
+
**At-least-once delivery** - duplicates possible. Make idempotent:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
export default {
|
|
36
|
+
async scheduled(controller, env, ctx) {
|
|
37
|
+
const execId = `${controller.scheduledTime}-${controller.cron}`;
|
|
38
|
+
if (await env.KV.get(`exec:${execId}`)) return;
|
|
39
|
+
await env.KV.put(`exec:${execId}`, "processing", { expirationTtl: 3600 });
|
|
40
|
+
await performTask(env);
|
|
41
|
+
await env.KV.put(`exec:${execId}`, "complete", { expirationTtl: 86400 });
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Debugging Not Executing
|
|
47
|
+
|
|
48
|
+
**Check:** `scheduled()` exported, recent deploy, 15min wait, valid cron ([crontab.guru](https://crontab.guru/)), plan limits
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
export default {
|
|
52
|
+
async scheduled(controller, env, ctx) {
|
|
53
|
+
console.log("EXECUTED", {time: new Date().toISOString(), scheduledTime: new Date(controller.scheduledTime).toISOString(), cron: controller.cron});
|
|
54
|
+
ctx.waitUntil(env.KV.put("last_execution", Date.now().toString()));
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Execution Failures
|
|
60
|
+
|
|
61
|
+
**Common:** CPU exceeded, unhandled exceptions, network timeouts, binding misconfiguration
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
export default {
|
|
65
|
+
async scheduled(controller, env, ctx) {
|
|
66
|
+
try {
|
|
67
|
+
const abortCtrl = new AbortController();
|
|
68
|
+
const timeout = setTimeout(() => abortCtrl.abort(), 5000);
|
|
69
|
+
const response = await fetch("https://api.example.com/data", {signal: abortCtrl.signal});
|
|
70
|
+
clearTimeout(timeout);
|
|
71
|
+
if (!response.ok) throw new Error(`API: ${response.status}`);
|
|
72
|
+
await processData(await response.json(), env);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error("Failed", {error: error.message, cron: controller.cron});
|
|
75
|
+
// Don't re-throw to mark success despite errors
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Local Testing Issues
|
|
82
|
+
|
|
83
|
+
Ensure `wrangler dev` runs, `scheduled()` exists, update Wrangler: `npm i -g wrangler@latest`
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
curl "http://localhost:8787/__scheduled?cron=*/5+*+*+*+*" # URL encode spaces
|
|
87
|
+
curl "http://localhost:8787/__scheduled" # No params = default
|
|
88
|
+
# Python: curl "http://localhost:8787/cdn-cgi/handler/scheduled?cron=*/5+*+*+*+*"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Security
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
export default {
|
|
95
|
+
async fetch(request, env, ctx) {
|
|
96
|
+
const url = new URL(request.url);
|
|
97
|
+
if (url.pathname === "/__scheduled") {
|
|
98
|
+
if (env.ENVIRONMENT === "production") return new Response("Not found", { status: 404 });
|
|
99
|
+
await this.scheduled({scheduledTime: Date.now(), cron: url.searchParams.get("cron") || "* * * * *", type: "scheduled"}, env, ctx);
|
|
100
|
+
return new Response("OK");
|
|
101
|
+
}
|
|
102
|
+
return new Response("Hello");
|
|
103
|
+
},
|
|
104
|
+
async scheduled(controller, env, ctx) {},
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Secrets Management
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// ❌ BAD: headers: { "Authorization": "Bearer sk_live_abc123..." }
|
|
112
|
+
// ✅ GOOD: headers: { "Authorization": `Bearer ${env.API_KEY}` }
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx wrangler secret put API_KEY
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Green Compute
|
|
120
|
+
|
|
121
|
+
Dashboard: Workers & Pages → Account details → Compute Setting → Green Compute. Tradeoffs: fewer locations, higher latency, ideal for non-time-critical jobs
|
|
122
|
+
|
|
123
|
+
## Resources
|
|
124
|
+
|
|
125
|
+
- [Cron Triggers Docs](https://developers.cloudflare.com/workers/configuration/cron-triggers/)
|
|
126
|
+
- [Scheduled Handler API](https://developers.cloudflare.com/workers/runtime-apis/handlers/scheduled/)
|
|
127
|
+
- [Cloudflare Workflows](https://developers.cloudflare.com/workflows/)
|
|
128
|
+
- [Workers Limits](https://developers.cloudflare.com/workers/platform/limits/)
|
|
129
|
+
- [Crontab Guru](https://crontab.guru/) - Validator
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Cron Triggers Patterns
|
|
2
|
+
|
|
3
|
+
## API Data Sync
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
export default {
|
|
7
|
+
async scheduled(controller, env, ctx) {
|
|
8
|
+
const response = await fetch("https://api.example.com/data", {headers: { "Authorization": `Bearer ${env.API_KEY}` }});
|
|
9
|
+
if (!response.ok) throw new Error(`API error: ${response.status}`);
|
|
10
|
+
ctx.waitUntil(env.MY_KV.put("cached_data", JSON.stringify(await response.json()), {expirationTtl: 3600}));
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Database Cleanup
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
export default {
|
|
19
|
+
async scheduled(controller, env, ctx) {
|
|
20
|
+
const result = await env.DB.prepare(`DELETE FROM sessions WHERE expires_at < datetime('now')`).run();
|
|
21
|
+
console.log(`Deleted ${result.meta.changes} expired sessions`);
|
|
22
|
+
ctx.waitUntil(env.DB.prepare("VACUUM").run());
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Report Generation
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
export default {
|
|
31
|
+
async scheduled(controller, env, ctx) {
|
|
32
|
+
const startOfWeek = new Date(); startOfWeek.setDate(startOfWeek.getDate() - 7);
|
|
33
|
+
const { results } = await env.DB.prepare(`SELECT date, revenue, orders FROM daily_stats WHERE date >= ? ORDER BY date`).bind(startOfWeek.toISOString()).all();
|
|
34
|
+
const report = {period: "weekly", totalRevenue: results.reduce((sum, d) => sum + d.revenue, 0), totalOrders: results.reduce((sum, d) => sum + d.orders, 0), dailyBreakdown: results};
|
|
35
|
+
const reportKey = `reports/weekly-${Date.now()}.json`;
|
|
36
|
+
await env.REPORTS_BUCKET.put(reportKey, JSON.stringify(report));
|
|
37
|
+
ctx.waitUntil(env.SEND_EMAIL.fetch("https://example.com/send", {method: "POST", body: JSON.stringify({to: "team@example.com", subject: "Weekly Report", reportUrl: `https://reports.example.com/${reportKey}`})}));
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Health Checks
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
export default {
|
|
46
|
+
async scheduled(controller, env, ctx) {
|
|
47
|
+
const services = [{name: "API", url: "https://api.example.com/health"}, {name: "CDN", url: "https://cdn.example.com/health"}];
|
|
48
|
+
const checks = await Promise.all(services.map(async (service) => {
|
|
49
|
+
const start = Date.now();
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(service.url, { signal: AbortSignal.timeout(5000) });
|
|
52
|
+
return {name: service.name, status: response.ok ? "up" : "down", responseTime: Date.now() - start};
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return {name: service.name, status: "down", responseTime: Date.now() - start, error: error.message};
|
|
55
|
+
}
|
|
56
|
+
}));
|
|
57
|
+
ctx.waitUntil(env.STATUS_KV.put("health_status", JSON.stringify(checks)));
|
|
58
|
+
const failures = checks.filter(c => c.status === "down");
|
|
59
|
+
if (failures.length > 0) ctx.waitUntil(fetch(env.ALERT_WEBHOOK, {method: "POST", body: JSON.stringify({text: `${failures.length} service(s) down: ${failures.map(f => f.name).join(", ")}`})}));
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Batch Processing (Rate-Limited)
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
export default {
|
|
68
|
+
async scheduled(controller, env, ctx) {
|
|
69
|
+
const queueData = await env.QUEUE_KV.get("pending_items", "json");
|
|
70
|
+
if (!queueData || queueData.length === 0) return;
|
|
71
|
+
const batch = queueData.slice(0, 100);
|
|
72
|
+
const results = await Promise.allSettled(batch.map(item => fetch("https://api.example.com/process", {method: "POST", headers: {"Authorization": `Bearer ${env.API_KEY}`, "Content-Type": "application/json"}, body: JSON.stringify(item)})));
|
|
73
|
+
console.log(`Processed ${results.filter(r => r.status === "fulfilled").length}/${batch.length} items`);
|
|
74
|
+
ctx.waitUntil(env.QUEUE_KV.put("pending_items", JSON.stringify(queueData.slice(100))));
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Monitoring & Logging
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
export default {
|
|
83
|
+
async scheduled(controller, env, ctx) {
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
console.log(`[START] Cron ${controller.cron} at ${new Date(controller.scheduledTime).toISOString()}`);
|
|
86
|
+
try {
|
|
87
|
+
const result = await performTask(env);
|
|
88
|
+
const duration = Date.now() - startTime;
|
|
89
|
+
console.log(`[SUCCESS] Completed in ${duration}ms`, {cron: controller.cron, recordsProcessed: result.count});
|
|
90
|
+
ctx.waitUntil(logToExternal(env.ANALYTICS_ENDPOINT, {event: "cron_success", duration, cron: controller.cron}));
|
|
91
|
+
} catch (error) {
|
|
92
|
+
const duration = Date.now() - startTime;
|
|
93
|
+
console.error(`[ERROR] Failed after ${duration}ms`, {cron: controller.cron, error: error.message});
|
|
94
|
+
ctx.waitUntil(notifyFailure(env.ALERT_WEBHOOK, {cron: controller.cron, error: error.message}));
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## View Past Events
|
|
102
|
+
|
|
103
|
+
**Dashboard:** Workers & Pages → Select Worker → Settings → Triggers → Cron Events
|
|
104
|
+
|
|
105
|
+
**Wrangler:**
|
|
106
|
+
```bash
|
|
107
|
+
npx wrangler tail
|
|
108
|
+
npx wrangler tail --format json | jq 'select(.event.cron != null)'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**GraphQL:**
|
|
112
|
+
```graphql
|
|
113
|
+
query CronMetrics($accountTag: string!, $workerName: string!) {
|
|
114
|
+
viewer { accounts(filter: { accountTag: $accountTag }) { workersInvocationsAdaptive(filter: {scriptName: $workerName, eventType: "scheduled"}, limit: 100) { dimensions { datetime, status }, sum { requests, errors } } } }
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## See Also
|
|
119
|
+
|
|
120
|
+
- [README.md](./README.md) - Overview
|
|
121
|
+
- [api.md](./api.md) - Handler implementation
|
|
122
|
+
- [gotchas.md](./gotchas.md) - Troubleshooting
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Cloudflare D1 Database
|
|
2
|
+
|
|
3
|
+
Expert guidance for Cloudflare D1, a serverless SQLite database designed for horizontal scale-out across multiple databases.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
D1 is Cloudflare's managed, serverless database with:
|
|
8
|
+
- SQLite SQL semantics and compatibility
|
|
9
|
+
- Built-in disaster recovery via Time Travel (30-day point-in-time recovery)
|
|
10
|
+
- Horizontal scale-out architecture (10 GB per database)
|
|
11
|
+
- Worker and HTTP API access
|
|
12
|
+
- Pricing based on query and storage costs only
|
|
13
|
+
|
|
14
|
+
**Architecture Philosophy**: D1 is optimized for per-user, per-tenant, or per-entity database patterns rather than single large databases.
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Create database
|
|
20
|
+
wrangler d1 create <database-name>
|
|
21
|
+
|
|
22
|
+
# Execute migration
|
|
23
|
+
wrangler d1 execute <db-name> --remote --file=./migrations/0001_schema.sql
|
|
24
|
+
|
|
25
|
+
# Local development
|
|
26
|
+
wrangler dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Core Query Methods
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
// .all() - Returns all rows; .first() - First row or null; .first(col) - Single column value
|
|
33
|
+
// .run() - INSERT/UPDATE/DELETE; .raw() - Array of arrays (efficient)
|
|
34
|
+
const { results, success, meta } = await env.DB.prepare('SELECT * FROM users WHERE active = ?').bind(true).all();
|
|
35
|
+
const user = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Batch Operations
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// Multiple queries in single round trip (atomic transaction)
|
|
42
|
+
const results = await env.DB.batch([
|
|
43
|
+
env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(1),
|
|
44
|
+
env.DB.prepare('SELECT * FROM posts WHERE author_id = ?').bind(1),
|
|
45
|
+
env.DB.prepare('UPDATE users SET last_access = ? WHERE id = ?').bind(Date.now(), 1)
|
|
46
|
+
]);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Platform Limits
|
|
50
|
+
|
|
51
|
+
| Limit | Value |
|
|
52
|
+
|-------|-------|
|
|
53
|
+
| Database size | 10 GB per database |
|
|
54
|
+
| Row size | 1 MB maximum |
|
|
55
|
+
| Query timeout | 30 seconds |
|
|
56
|
+
| Batch size | 10,000 statements |
|
|
57
|
+
| Time Travel retention | 30 days |
|
|
58
|
+
|
|
59
|
+
## CLI Commands
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Database management
|
|
63
|
+
wrangler d1 create <db-name>
|
|
64
|
+
wrangler d1 list
|
|
65
|
+
wrangler d1 delete <db-name>
|
|
66
|
+
|
|
67
|
+
# Execute queries
|
|
68
|
+
wrangler d1 execute <db-name> --remote --command="SELECT * FROM users"
|
|
69
|
+
wrangler d1 execute <db-name> --local --file=./migrations/0001_schema.sql
|
|
70
|
+
|
|
71
|
+
# Backups
|
|
72
|
+
wrangler d1 export <db-name> --remote --output=./backup.sql
|
|
73
|
+
wrangler d1 time-travel restore <db-name> --timestamp="2024-01-15T14:30:00Z"
|
|
74
|
+
|
|
75
|
+
# Development
|
|
76
|
+
wrangler dev --persist-to=./.wrangler/state
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## In This Reference
|
|
80
|
+
|
|
81
|
+
- [configuration.md](./configuration.md) - wrangler.toml setup, TypeScript types, binding configuration
|
|
82
|
+
- [api.md](./api.md) - D1Database API, prepared statements, batch operations, testing
|
|
83
|
+
- [patterns.md](./patterns.md) - Pagination, bulk operations, caching, multi-tenant patterns
|
|
84
|
+
- [gotchas.md](./gotchas.md) - SQL injection prevention, error handling, performance pitfalls
|
|
85
|
+
|
|
86
|
+
## See Also
|
|
87
|
+
|
|
88
|
+
- [workers](../workers/) - Worker runtime and fetch handler patterns
|
|
89
|
+
- [kv](../kv/) - Workers KV for caching D1 results
|
|
90
|
+
- [r2](../r2/) - R2 for storing binary data instead of D1 BLOBs
|
|
91
|
+
- [queues](../queues/) - Queue writes to D1 for high-throughput scenarios
|
|
92
|
+
- [durable-objects](../durable-objects/) - Coordinate D1 writes with strong consistency
|