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,125 @@
|
|
|
1
|
+
# Workflow APIs
|
|
2
|
+
|
|
3
|
+
## Step APIs
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// step.do()
|
|
7
|
+
const result = await step.do('step name', async () => { /* logic */ });
|
|
8
|
+
const result = await step.do('step name', { retries, timeout }, async () => {});
|
|
9
|
+
|
|
10
|
+
// step.sleep()
|
|
11
|
+
await step.sleep('description', '1 hour');
|
|
12
|
+
await step.sleep('description', 5000); // ms
|
|
13
|
+
|
|
14
|
+
// step.sleepUntil()
|
|
15
|
+
await step.sleepUntil('description', Date.parse('2024-12-31'));
|
|
16
|
+
|
|
17
|
+
// step.waitForEvent()
|
|
18
|
+
const data = await step.waitForEvent<PayloadType>('wait', {type: 'webhook-type', timeout: '24h'}); // Default 24h, max 365d
|
|
19
|
+
try { const event = await step.waitForEvent('wait', { type: 'approval', timeout: '1h' }); } catch (e) { /* Timeout */ }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Instance Management
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// Create single
|
|
26
|
+
const instance = await env.MY_WORKFLOW.create({id: crypto.randomUUID(), params: { userId: 'user123' }}); // id optional, auto-generated if omitted
|
|
27
|
+
|
|
28
|
+
// Batch (max 100, idempotent: skips existing IDs)
|
|
29
|
+
const instances = await env.MY_WORKFLOW.createBatch([{id: 'user1', params: {name: 'John'}}, {id: 'user2', params: {name: 'Jane'}}]);
|
|
30
|
+
|
|
31
|
+
// Get & Status
|
|
32
|
+
const instance = await env.MY_WORKFLOW.get('instance-id');
|
|
33
|
+
const status = await instance.status(); // {status: 'queued' | 'running' | 'paused' | 'errored' | 'terminated' | 'complete' | 'waiting' | 'waitingForPause' | 'unknown', error?, output?}
|
|
34
|
+
|
|
35
|
+
// Control
|
|
36
|
+
await instance.pause(); await instance.resume(); await instance.terminate(); await instance.restart();
|
|
37
|
+
|
|
38
|
+
// Send Events
|
|
39
|
+
await instance.sendEvent({type: 'approval', payload: { approved: true }}); // Must match waitForEvent type
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Triggering Workflows
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// From Worker
|
|
46
|
+
export default { async fetch(req, env) { const instance = await env.MY_WORKFLOW.create({id: crypto.randomUUID(), params: { userId: 'user123' }}); return Response.json({ id: instance.id }); }};
|
|
47
|
+
|
|
48
|
+
// From Queue
|
|
49
|
+
export default { async queue(batch, env) { for (const msg of batch.messages) { await env.MY_WORKFLOW.create({id: `job-${msg.id}`, params: msg.body}); } }};
|
|
50
|
+
|
|
51
|
+
// From Cron
|
|
52
|
+
export default { async scheduled(event, env) { await env.CLEANUP_WORKFLOW.create({id: `cleanup-${Date.now()}`, params: { timestamp: event.scheduledTime }}); }};
|
|
53
|
+
|
|
54
|
+
// From Another Workflow (non-blocking)
|
|
55
|
+
export class ParentWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
56
|
+
async run(event, step) {
|
|
57
|
+
const child = await step.do('start child', async () => await this.env.CHILD_WORKFLOW.create({id: `child-${event.instanceId}`, params: {}}));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Error Handling
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { NonRetryableError } from 'cloudflare:workflows';
|
|
66
|
+
|
|
67
|
+
// NonRetryableError
|
|
68
|
+
await step.do('validate', async () => {
|
|
69
|
+
if (!event.payload.paymentMethod) throw new NonRetryableError('Payment method required');
|
|
70
|
+
const res = await fetch('https://api.example.com/charge', { method: 'POST' });
|
|
71
|
+
if (res.status === 401) throw new NonRetryableError('Invalid credentials'); // Don't retry
|
|
72
|
+
if (!res.ok) throw new Error('Retryable failure'); // Will retry
|
|
73
|
+
return res.json();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Catching Errors
|
|
77
|
+
try { await step.do('risky op', async () => { throw new NonRetryableError('Failed'); }); } catch (e) { await step.do('cleanup', async () => {}); }
|
|
78
|
+
|
|
79
|
+
// Idempotency
|
|
80
|
+
await step.do('charge', async () => {
|
|
81
|
+
const sub = await fetch(`https://api/subscriptions/${id}`).then(r => r.json());
|
|
82
|
+
if (sub.charged) return sub; // Already done
|
|
83
|
+
return await fetch(`https://api/subscriptions/${id}`, {method: 'POST', body: JSON.stringify({ amount: 10.0 })}).then(r => r.json());
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Wrangler CLI
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm create cloudflare@latest my-workflow -- --template "cloudflare/workflows-starter"
|
|
91
|
+
npx wrangler deploy
|
|
92
|
+
npx wrangler workflows list
|
|
93
|
+
npx wrangler workflows trigger my-workflow '{"userId":"user123"}'
|
|
94
|
+
npx wrangler workflows instances list my-workflow
|
|
95
|
+
npx wrangler workflows instances describe my-workflow instance-id
|
|
96
|
+
npx wrangler workflows instances pause/resume/terminate my-workflow instance-id
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## REST API
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Create
|
|
103
|
+
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/workflows/{workflow_name}/instances" -H "Authorization: Bearer {token}" -d '{"id":"custom-id","params":{"userId":"user123"}}'
|
|
104
|
+
|
|
105
|
+
# Status
|
|
106
|
+
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/workflows/{workflow_name}/instances/{instance_id}/status" -H "Authorization: Bearer {token}"
|
|
107
|
+
|
|
108
|
+
# Send Event
|
|
109
|
+
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/workflows/{workflow_name}/instances/{instance_id}/events" -H "Authorization: Bearer {token}" -d '{"type":"approval","payload":{"approved":true}}'
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Bindings
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
type Env = {MY_WORKFLOW: Workflow; KV: KVNamespace; DB: D1Database; BUCKET: R2Bucket; AI: Ai; VECTORIZE: VectorizeIndex;};
|
|
116
|
+
|
|
117
|
+
await step.do('use bindings', async () => {
|
|
118
|
+
const kv = await this.env.KV.get('key');
|
|
119
|
+
const db = await this.env.DB.prepare('SELECT * FROM users').first();
|
|
120
|
+
const file = await this.env.BUCKET.get('file.txt');
|
|
121
|
+
const ai = await this.env.AI.run('@cf/meta/llama-2-7b-chat-int8', { prompt: 'Hi' });
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
See: [configuration.md](./configuration.md), [patterns.md](./patterns.md)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Workflow Configuration
|
|
2
|
+
|
|
3
|
+
## Wrangler Setup
|
|
4
|
+
|
|
5
|
+
**wrangler.toml:**
|
|
6
|
+
```toml
|
|
7
|
+
name = "my-worker"
|
|
8
|
+
main = "src/index.ts"
|
|
9
|
+
compatibility_date = "2024-10-22"
|
|
10
|
+
|
|
11
|
+
[[workflows]]
|
|
12
|
+
name = "my-workflow" # Workflow name
|
|
13
|
+
binding = "MY_WORKFLOW" # Env binding
|
|
14
|
+
class_name = "MyWorkflow" # TS class name
|
|
15
|
+
# script_name = "other-worker" # For cross-script calls
|
|
16
|
+
|
|
17
|
+
[limits]
|
|
18
|
+
cpu_ms = 300_000 # 5 min max (default 30s)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**wrangler.jsonc:**
|
|
22
|
+
```jsonc
|
|
23
|
+
{
|
|
24
|
+
"name": "my-worker",
|
|
25
|
+
"workflows": [
|
|
26
|
+
{ "name": "my-workflow", "binding": "MY_WORKFLOW", "class_name": "MyWorkflow" }
|
|
27
|
+
],
|
|
28
|
+
"limits": { "cpu_ms": 300000 }
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Step Configuration
|
|
33
|
+
|
|
34
|
+
### Basic Step
|
|
35
|
+
```typescript
|
|
36
|
+
const data = await step.do('step name', async () => {
|
|
37
|
+
return { result: 'value' };
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Retry Config
|
|
42
|
+
```typescript
|
|
43
|
+
await step.do('api call', {
|
|
44
|
+
retries: {
|
|
45
|
+
limit: 10, // Default: 5, or Infinity
|
|
46
|
+
delay: '10 seconds', // Default: 10000ms
|
|
47
|
+
backoff: 'exponential' // constant | linear | exponential
|
|
48
|
+
},
|
|
49
|
+
timeout: '30 minutes' // Per-attempt timeout (default: 10min)
|
|
50
|
+
}, async () => {
|
|
51
|
+
const res = await fetch('https://api.example.com/data');
|
|
52
|
+
if (!res.ok) throw new Error('Failed');
|
|
53
|
+
return res.json();
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Parallel Steps
|
|
58
|
+
```typescript
|
|
59
|
+
const [user, settings] = await Promise.all([
|
|
60
|
+
step.do('fetch user', async () => this.env.KV.get(`user:${id}`)),
|
|
61
|
+
step.do('fetch settings', async () => this.env.KV.get(`settings:${id}`))
|
|
62
|
+
]);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Conditional Steps
|
|
66
|
+
```typescript
|
|
67
|
+
const config = await step.do('fetch config', async () =>
|
|
68
|
+
this.env.KV.get('flags', { type: 'json' })
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// ✅ Deterministic (based on step output)
|
|
72
|
+
if (config.enableEmail) {
|
|
73
|
+
await step.do('send email', async () => sendEmail());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ❌ Non-deterministic (Date.now outside step)
|
|
77
|
+
if (Date.now() > deadline) { /* BAD */ }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Dynamic Steps (Loops)
|
|
81
|
+
```typescript
|
|
82
|
+
const files = await step.do('list files', async () =>
|
|
83
|
+
this.env.BUCKET.list()
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
for (const file of files.objects) {
|
|
87
|
+
await step.do(`process ${file.key}`, async () => {
|
|
88
|
+
const obj = await this.env.BUCKET.get(file.key);
|
|
89
|
+
return processData(await obj.arrayBuffer());
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Sleep & Scheduling
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Relative
|
|
98
|
+
await step.sleep('wait 1 hour', '1 hour');
|
|
99
|
+
await step.sleep('wait 30 days', '30 days');
|
|
100
|
+
await step.sleep('wait 5s', 5000); // ms
|
|
101
|
+
|
|
102
|
+
// Absolute
|
|
103
|
+
await step.sleepUntil('launch date', Date.parse('24 Oct 2024 13:00:00 UTC'));
|
|
104
|
+
await step.sleepUntil('deadline', new Date('2024-12-31T23:59:59Z'));
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Units: second, minute, hour, day, week, month, year. Max: 365 days.
|
|
108
|
+
Sleeping instances don't count toward concurrency.
|
|
109
|
+
|
|
110
|
+
## Parameters
|
|
111
|
+
|
|
112
|
+
**Pass from Worker:**
|
|
113
|
+
```typescript
|
|
114
|
+
const instance = await env.MY_WORKFLOW.create({
|
|
115
|
+
id: crypto.randomUUID(),
|
|
116
|
+
params: { userId: 'user123', email: 'user@example.com' }
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Access in Workflow:**
|
|
121
|
+
```typescript
|
|
122
|
+
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
|
|
123
|
+
const userId = event.payload.userId;
|
|
124
|
+
const instanceId = event.instanceId;
|
|
125
|
+
const createdAt = event.timestamp;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**CLI Trigger:**
|
|
130
|
+
```bash
|
|
131
|
+
npx wrangler workflows trigger my-workflow '{"userId":"user123"}'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Multiple Workflows
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
export class UserOnboarding extends WorkflowEntrypoint<Env, UserParams> {
|
|
138
|
+
async run(event, step) { /* ... */ }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export class DataProcessing extends WorkflowEntrypoint<Env, DataParams> {
|
|
142
|
+
async run(event, step) { /* ... */ }
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```toml
|
|
147
|
+
[[workflows]]
|
|
148
|
+
name = "user-onboarding"
|
|
149
|
+
binding = "USER_ONBOARDING"
|
|
150
|
+
class_name = "UserOnboarding"
|
|
151
|
+
|
|
152
|
+
[[workflows]]
|
|
153
|
+
name = "data-processing"
|
|
154
|
+
binding = "DATA_PROCESSING"
|
|
155
|
+
class_name = "DataProcessing"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Cross-Script Bindings
|
|
159
|
+
|
|
160
|
+
**billing-worker** defines workflow:
|
|
161
|
+
```toml
|
|
162
|
+
[[workflows]]
|
|
163
|
+
name = "billing-workflow"
|
|
164
|
+
binding = "BILLING"
|
|
165
|
+
class_name = "BillingWorkflow"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**web-api-worker** calls it:
|
|
169
|
+
```toml
|
|
170
|
+
[[workflows]]
|
|
171
|
+
name = "billing-workflow"
|
|
172
|
+
binding = "BILLING"
|
|
173
|
+
class_name = "BillingWorkflow"
|
|
174
|
+
script_name = "billing-worker"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
See: [api.md](./api.md), [patterns.md](./patterns.md)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Gotchas & Debugging
|
|
2
|
+
|
|
3
|
+
## Timeout Issues
|
|
4
|
+
|
|
5
|
+
### Step Timeout
|
|
6
|
+
- **Default**: 10 min/attempt
|
|
7
|
+
- **CPU Limit**: 30s default, max 5min (wrangler.toml `limits.cpu_ms = 300_000`)
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
await step.do('long operation', {timeout: '30 minutes'}, async () => { /* ... */ });
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### waitForEvent Timeout
|
|
14
|
+
- **Default**: 24h, **Max**: 365d, **Throws on timeout**
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
try {
|
|
18
|
+
const event = await step.waitForEvent('wait', { type: 'approval', timeout: '1h' });
|
|
19
|
+
} catch (e) { /* Timeout - proceed with default */ }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Limits
|
|
23
|
+
|
|
24
|
+
| Limit | Free | Paid |
|
|
25
|
+
|-------|------|------|
|
|
26
|
+
| CPU per step | 10ms | 30s (default), 5min (max) |
|
|
27
|
+
| Step state | 1 MiB | 1 MiB |
|
|
28
|
+
| Instance state | 100 MB | 1 GB |
|
|
29
|
+
| Steps per workflow | 1,024 | 1,024 |
|
|
30
|
+
| Executions/day | 100k | Unlimited |
|
|
31
|
+
| Concurrent instances | 25 | 10k |
|
|
32
|
+
| State retention | 3d | 30d |
|
|
33
|
+
|
|
34
|
+
Note: `step.sleep()` doesn't count toward step limit
|
|
35
|
+
|
|
36
|
+
## Debugging
|
|
37
|
+
|
|
38
|
+
### Logs
|
|
39
|
+
```typescript
|
|
40
|
+
await step.do('process', async () => {
|
|
41
|
+
console.log('Logged once per successful step'); // ✅
|
|
42
|
+
return result;
|
|
43
|
+
});
|
|
44
|
+
console.log('Outside step'); // ⚠️ May duplicate on restart
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Instance Status
|
|
48
|
+
```bash
|
|
49
|
+
npx wrangler workflows instances describe my-workflow instance-id
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const instance = await env.MY_WORKFLOW.get('instance-id');
|
|
54
|
+
const status = await instance.status();
|
|
55
|
+
// status: queued | running | paused | errored | terminated | complete | waiting | waitingForPause | unknown
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Common Pitfalls
|
|
59
|
+
|
|
60
|
+
### Non-Deterministic Step Names
|
|
61
|
+
```typescript
|
|
62
|
+
// ❌ BAD: await step.do(`step-${Date.now()}`, ...)
|
|
63
|
+
// ✅ GOOD: await step.do(`step-${event.instanceId}`, ...)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### State in Variables
|
|
67
|
+
```typescript
|
|
68
|
+
// ❌ BAD: let total = 0; await step.do('step 1', async () => { total += 10; }); // Lost on hibernation
|
|
69
|
+
// ✅ GOOD: const total = await step.do('step 1', async () => 10); // Persisted
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Non-Deterministic Conditionals
|
|
73
|
+
```typescript
|
|
74
|
+
// ❌ BAD: if (Date.now() > deadline) { await step.do(...) }
|
|
75
|
+
// ✅ GOOD: const isLate = await step.do('check', async () => Date.now() > deadline); if (isLate) { await step.do(...) }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Large Step Returns
|
|
79
|
+
```typescript
|
|
80
|
+
// ❌ BAD: return await fetchHugeDataset(); // 5 MiB
|
|
81
|
+
// ✅ GOOD: Store in R2, return { key }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Idempotency Ignored
|
|
85
|
+
```typescript
|
|
86
|
+
// ❌ BAD: await step.do('charge', async () => await chargeCustomer(...)); // Charges on retry
|
|
87
|
+
// ✅ GOOD: Check if already charged first
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Instance ID Collision
|
|
91
|
+
```typescript
|
|
92
|
+
// ❌ BAD: await env.MY_WORKFLOW.create({ id: userId, params: {} }); // Reuses IDs
|
|
93
|
+
// ✅ GOOD: await env.MY_WORKFLOW.create({ id: `${userId}-${Date.now()}`, params: {} });
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Missing await
|
|
97
|
+
```typescript
|
|
98
|
+
// ❌ BAD: step.do('task', ...); // Fire-and-forget
|
|
99
|
+
// ✅ GOOD: await step.do('task', ...);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Pricing
|
|
103
|
+
|
|
104
|
+
| Metric | Free | Paid |
|
|
105
|
+
|--------|------|------|
|
|
106
|
+
| Requests | 100k/day | 10M/mo + $0.30/M |
|
|
107
|
+
| CPU time | 10ms/invoke | 30M CPU-ms/mo + $0.02/M CPU-ms |
|
|
108
|
+
| Storage | 1 GB | 1 GB/mo + $0.20/GB-mo |
|
|
109
|
+
|
|
110
|
+
Storage: Includes all instances (running/errored/sleeping/completed). Retention: 3d (Free), 30d (Paid)
|
|
111
|
+
|
|
112
|
+
## TypeScript Types
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent, NonRetryableError } from 'cloudflare:workers';
|
|
116
|
+
|
|
117
|
+
interface Env { MY_WORKFLOW: Workflow<MyParams>; KV: KVNamespace; DB: D1Database; }
|
|
118
|
+
|
|
119
|
+
export class MyWorkflow extends WorkflowEntrypoint<Env, MyParams> {
|
|
120
|
+
async run(event: WorkflowEvent<MyParams>, step: WorkflowStep) {
|
|
121
|
+
const user = await step.do('fetch', async () => await this.env.KV.get<User>(`user:${event.payload.userId}`, { type: 'json' }));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## References
|
|
127
|
+
|
|
128
|
+
- [Official Docs](https://developers.cloudflare.com/workflows/)
|
|
129
|
+
- [Get Started Guide](https://developers.cloudflare.com/workflows/get-started/guide/)
|
|
130
|
+
- [Workers API](https://developers.cloudflare.com/workflows/build/workers-api/)
|
|
131
|
+
- [REST API](https://developers.cloudflare.com/api/resources/workflows/)
|
|
132
|
+
- [Examples](https://developers.cloudflare.com/workflows/examples/)
|
|
133
|
+
- [Limits](https://developers.cloudflare.com/workflows/reference/limits/)
|
|
134
|
+
- [Pricing](https://developers.cloudflare.com/workflows/reference/pricing/)
|
|
135
|
+
|
|
136
|
+
See: [README.md](./README.md), [configuration.md](./configuration.md), [api.md](./api.md), [patterns.md](./patterns.md)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Workflow Patterns
|
|
2
|
+
|
|
3
|
+
## Image Processing Pipeline
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
export class ImageProcessingWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
7
|
+
async run(event, step) {
|
|
8
|
+
const imageData = await step.do('fetch', async () => (await this.env.BUCKET.get(event.payload.imageKey)).arrayBuffer());
|
|
9
|
+
const description = await step.do('generate description', async () =>
|
|
10
|
+
await this.env.AI.run('@cf/llava-hf/llava-1.5-7b-hf', {image: Array.from(new Uint8Array(imageData)), prompt: 'Describe this image', max_tokens: 50})
|
|
11
|
+
);
|
|
12
|
+
await step.waitForEvent('await approval', { type: 'approved', timeout: '24h' });
|
|
13
|
+
await step.do('publish', async () => await this.env.BUCKET.put(`public/${event.payload.imageKey}`, imageData));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## User Lifecycle
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
export class UserLifecycleWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
22
|
+
async run(event, step) {
|
|
23
|
+
await step.do('welcome email', async () => await sendEmail(event.payload.email, 'Welcome!'));
|
|
24
|
+
await step.sleep('trial period', '7 days');
|
|
25
|
+
const hasConverted = await step.do('check conversion', async () => {
|
|
26
|
+
const user = await this.env.DB.prepare('SELECT subscription_status FROM users WHERE id = ?').bind(event.payload.userId).first();
|
|
27
|
+
return user.subscription_status === 'active';
|
|
28
|
+
});
|
|
29
|
+
if (!hasConverted) await step.do('trial expiration email', async () => await sendEmail(event.payload.email, 'Trial ending'));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Data Pipeline
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
export class DataPipelineWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
38
|
+
async run(event, step) {
|
|
39
|
+
const rawData = await step.do('extract', {retries: { limit: 10, delay: '30s', backoff: 'exponential' }, timeout: '5 minutes'}, async () => {
|
|
40
|
+
const res = await fetch(event.payload.sourceUrl);
|
|
41
|
+
if (!res.ok) throw new Error('Fetch failed');
|
|
42
|
+
return res.json();
|
|
43
|
+
});
|
|
44
|
+
const transformed = await step.do('transform', async () => rawData.map(item => ({ id: item.id, normalized: normalizeData(item) })));
|
|
45
|
+
const dataRef = await step.do('store', async () => {
|
|
46
|
+
const key = `processed/${Date.now()}.json`;
|
|
47
|
+
await this.env.BUCKET.put(key, JSON.stringify(transformed));
|
|
48
|
+
return { key };
|
|
49
|
+
});
|
|
50
|
+
await step.do('load', {retries: { limit: 5, delay: '1m', backoff: 'linear' }}, async () => {
|
|
51
|
+
const data = await (await this.env.BUCKET.get(dataRef.key)).json();
|
|
52
|
+
for (let i = 0; i < data.length; i += 100) {
|
|
53
|
+
await this.env.DB.batch(data.slice(i, i + 100).map(item => this.env.DB.prepare('INSERT INTO records VALUES (?, ?)').bind(item.id, item.normalized)));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Human-in-the-Loop Approval
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
export class ApprovalWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
64
|
+
async run(event, step) {
|
|
65
|
+
await step.do('create approval', async () => await this.env.DB.prepare('INSERT INTO approvals (id, user_id, status) VALUES (?, ?, ?)').bind(event.instanceId, event.payload.userId, 'pending').run());
|
|
66
|
+
try {
|
|
67
|
+
const approval = await step.waitForEvent<{ approved: boolean }>('wait for approval', { type: 'approval-response', timeout: '48h' });
|
|
68
|
+
if (approval.approved) { await step.do('process approval', async () => {}); }
|
|
69
|
+
else { await step.do('handle rejection', async () => {}); }
|
|
70
|
+
} catch (e) {
|
|
71
|
+
await step.do('auto reject', async () => await this.env.DB.prepare('UPDATE approvals SET status = ? WHERE id = ?').bind('auto-rejected', event.instanceId).run());
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Best Practices
|
|
78
|
+
|
|
79
|
+
### ✅ DO
|
|
80
|
+
|
|
81
|
+
1. **Granular steps**: One API call per step (unless proving idempotency)
|
|
82
|
+
2. **Idempotency**: Check-then-execute; use idempotency keys
|
|
83
|
+
3. **Deterministic names**: Use static or step-output-based names
|
|
84
|
+
4. **Return state**: Persist via step returns, not variables
|
|
85
|
+
5. **Always await**: `await step.do()`, avoid dangling promises
|
|
86
|
+
6. **Deterministic conditionals**: Base on `event.payload` or step outputs
|
|
87
|
+
7. **Store large data externally**: R2/KV for >1 MiB, return refs
|
|
88
|
+
8. **Batch creation**: `createBatch()` for multiple instances
|
|
89
|
+
|
|
90
|
+
### ❌ DON'T
|
|
91
|
+
|
|
92
|
+
1. **One giant step**: Breaks durability & retry control
|
|
93
|
+
2. **State outside steps**: Lost on hibernation
|
|
94
|
+
3. **Mutate events**: Events immutable, return new state
|
|
95
|
+
4. **Non-deterministic logic outside steps**: `Math.random()`, `Date.now()` must be in steps
|
|
96
|
+
5. **Side effects outside steps**: May duplicate on restart
|
|
97
|
+
6. **Non-deterministic step names**: Prevents caching
|
|
98
|
+
7. **Ignore timeouts**: `waitForEvent` throws, use try-catch
|
|
99
|
+
8. **Reuse instance IDs**: Must be unique within retention
|
|
100
|
+
|
|
101
|
+
## Orchestration Patterns
|
|
102
|
+
|
|
103
|
+
### Fan-Out (Parallel Processing)
|
|
104
|
+
```typescript
|
|
105
|
+
const files = await step.do('list', async () => this.env.BUCKET.list());
|
|
106
|
+
await Promise.all(files.objects.map((file, i) => step.do(`process ${i}`, async () => processFile(await (await this.env.BUCKET.get(file.key)).arrayBuffer()))));
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Parent-Child Workflows
|
|
110
|
+
```typescript
|
|
111
|
+
const child = await step.do('start child', async () => await this.env.CHILD_WORKFLOW.create({id: `child-${event.instanceId}`, params: { data: result.data }}));
|
|
112
|
+
await step.do('other work', async () => console.log(`Child started: ${child.id}`));
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Promise.race
|
|
116
|
+
```typescript
|
|
117
|
+
const result = await step.do('race', async () => await Promise.race([step.do('option A', async () => { await sleep(1000); return 'A'; }), step.do('option B', async () => 'B')]));
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Scheduled Workflow Chain
|
|
121
|
+
```typescript
|
|
122
|
+
export default { async scheduled(event, env) { await env.DAILY_WORKFLOW.create({id: `daily-${event.scheduledTime}`, params: { timestamp: event.scheduledTime }}); }};
|
|
123
|
+
export class DailyWorkflow extends WorkflowEntrypoint<Env, Params> {
|
|
124
|
+
async run(event, step) {
|
|
125
|
+
await step.do('daily task', async () => {});
|
|
126
|
+
await step.sleep('wait 7 days', '7 days');
|
|
127
|
+
await step.do('weekly followup', async () => {});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
See: [configuration.md](./configuration.md), [api.md](./api.md), [gotchas.md](./gotchas.md)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Cloudflare Wrangler
|
|
2
|
+
|
|
3
|
+
Official CLI for Cloudflare Workers - develop, manage, and deploy Workers from the command line.
|
|
4
|
+
|
|
5
|
+
## What is Wrangler?
|
|
6
|
+
|
|
7
|
+
Wrangler is the Cloudflare Developer Platform CLI that allows you to:
|
|
8
|
+
- Create, develop, and deploy Workers
|
|
9
|
+
- Manage bindings (KV, D1, R2, Durable Objects, etc.)
|
|
10
|
+
- Configure routing and environments
|
|
11
|
+
- Run local development servers
|
|
12
|
+
- Execute migrations and manage resources
|
|
13
|
+
- Perform integration testing
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install wrangler --save-dev
|
|
19
|
+
# or globally
|
|
20
|
+
npm install -g wrangler
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Run commands: `npx wrangler <command>` (or `pnpm`/`yarn wrangler`)
|
|
24
|
+
|
|
25
|
+
## Essential Commands
|
|
26
|
+
|
|
27
|
+
### Project & Development
|
|
28
|
+
```bash
|
|
29
|
+
wrangler init [name] # Create new project
|
|
30
|
+
wrangler dev # Local dev server
|
|
31
|
+
wrangler dev --remote # Dev with remote resources
|
|
32
|
+
wrangler deploy # Deploy to production
|
|
33
|
+
wrangler deploy --env staging # Deploy to environment
|
|
34
|
+
wrangler versions list # List versions
|
|
35
|
+
wrangler rollback [id] # Rollback deployment
|
|
36
|
+
wrangler login # OAuth login
|
|
37
|
+
wrangler whoami # Check auth status
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Resource Management
|
|
41
|
+
|
|
42
|
+
### KV
|
|
43
|
+
```bash
|
|
44
|
+
wrangler kv namespace create NAME
|
|
45
|
+
wrangler kv key put "key" "value" --namespace-id=<id>
|
|
46
|
+
wrangler kv key get "key" --namespace-id=<id>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### D1
|
|
50
|
+
```bash
|
|
51
|
+
wrangler d1 create NAME
|
|
52
|
+
wrangler d1 execute NAME --command "SQL"
|
|
53
|
+
wrangler d1 migrations create NAME "description"
|
|
54
|
+
wrangler d1 migrations apply NAME
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### R2
|
|
58
|
+
```bash
|
|
59
|
+
wrangler r2 bucket create NAME
|
|
60
|
+
wrangler r2 object put BUCKET/key --file path
|
|
61
|
+
wrangler r2 object get BUCKET/key
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Other Resources
|
|
65
|
+
```bash
|
|
66
|
+
wrangler queues create NAME
|
|
67
|
+
wrangler vectorize create NAME --dimensions N --metric cosine
|
|
68
|
+
wrangler hyperdrive create NAME --connection-string "..."
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Secrets
|
|
72
|
+
```bash
|
|
73
|
+
wrangler secret put NAME # Set secret
|
|
74
|
+
wrangler secret list # List secrets
|
|
75
|
+
wrangler secret delete NAME # Delete secret
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Monitoring
|
|
79
|
+
```bash
|
|
80
|
+
wrangler tail # Real-time logs
|
|
81
|
+
wrangler tail --env production # Tail specific env
|
|
82
|
+
wrangler tail --status error # Filter by status
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## In This Reference
|
|
86
|
+
|
|
87
|
+
- [configuration.md](./configuration.md) - wrangler.jsonc setup, environments, bindings
|
|
88
|
+
- [api.md](./api.md) - Programmatic API (`unstable_startWorker`, `getPlatformProxy`)
|
|
89
|
+
- [patterns.md](./patterns.md) - Common workflows and development patterns
|
|
90
|
+
- [gotchas.md](./gotchas.md) - Common pitfalls, limits, and troubleshooting
|