opencodekit 0.15.4 → 0.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/template/.opencode/command/cloudflare.md +70 -0
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/skill/cloudflare/SKILL.md +233 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/README.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/api.md +100 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/configuration.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/gotchas.md +59 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/patterns.md +89 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-gateway/README.md +695 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/api.md +38 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/configuration.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/gotchas.md +41 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/patterns.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/api.md +27 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/configuration.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/gotchas.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/patterns.md +36 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/README.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/api.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/configuration.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/gotchas.md +28 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/patterns.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/README.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/api.md +78 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/configuration.md +128 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/gotchas.md +51 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/patterns.md +145 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/api.md +50 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/configuration.md +53 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/gotchas.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/patterns.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/configuration.md +58 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/gotchas.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/patterns.md +37 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/README.md +71 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/api.md +168 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/configuration.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/gotchas.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/patterns.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/api.md +54 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/configuration.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/gotchas.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/patterns.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/c3/README.md +264 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/README.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/api.md +176 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/configuration.md +164 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/gotchas.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/patterns.md +180 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/api.md +43 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/configuration.md +56 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/gotchas.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/patterns.md +40 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/README.md +85 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/api.md +198 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/configuration.md +151 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/gotchas.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/patterns.md +122 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/README.md +92 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/api.md +141 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/gotchas.md +70 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/patterns.md +144 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/README.md +34 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/api.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/configuration.md +67 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/gotchas.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/patterns.md +158 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/api.md +89 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/configuration.md +116 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/gotchas.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/patterns.md +112 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/README.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/api.md +152 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/configuration.md +148 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/gotchas.md +158 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/patterns.md +255 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/api.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/configuration.md +63 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/gotchas.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/patterns.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-workers/README.md +598 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/api.md +137 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/configuration.md +133 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/gotchas.md +184 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/patterns.md +176 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/configuration.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/gotchas.md +23 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/patterns.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/README.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/api.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/configuration.md +92 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/gotchas.md +117 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/patterns.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/README.md +64 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/api.md +144 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/configuration.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/gotchas.md +187 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/patterns.md +211 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/README.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/api.md +240 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/gotchas.md +171 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/patterns.md +171 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/api.md +51 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/configuration.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/gotchas.md +36 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/README.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/api.md +200 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/configuration.md +228 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/gotchas.md +161 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/patterns.md +145 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/README.md +57 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/api.md +201 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/configuration.md +159 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/gotchas.md +151 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/patterns.md +190 -0
- package/dist/template/.opencode/skill/cloudflare/references/pipelines/README.md +664 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/README.md +107 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/api.md +194 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/configuration.md +216 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/gotchas.md +223 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/patterns.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/README.md +69 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/api.md +138 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/configuration.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/gotchas.md +112 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/patterns.md +155 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/README.md +61 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/api.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/configuration.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/gotchas.md +94 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/patterns.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/api.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/configuration.md +39 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/gotchas.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/patterns.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-sql/README.md +512 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/README.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/api.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/configuration.md +63 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/gotchas.md +75 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/patterns.md +102 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/README.md +81 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/api.md +164 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/configuration.md +147 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/gotchas.md +172 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/patterns.md +155 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/README.md +90 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/api.md +178 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/configuration.md +131 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/gotchas.md +156 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/patterns.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/README.md +58 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/api.md +182 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/configuration.md +140 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/gotchas.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/patterns.md +218 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/README.md +91 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/api.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/configuration.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/gotchas.md +87 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/patterns.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/README.md +15 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/api.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/configuration.md +33 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/gotchas.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/patterns.md +34 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/api.md +24 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/configuration.md +43 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/gotchas.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/patterns.md +40 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/configuration.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/gotchas.md +44 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/README.md +103 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/api.md +204 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/gotchas.md +131 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/patterns.md +152 -0
- package/dist/template/.opencode/skill/cloudflare/references/tail-workers/README.md +640 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/README.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/api.md +159 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/configuration.md +156 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/gotchas.md +207 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/patterns.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/README.md +82 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/api.md +105 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/configuration.md +113 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/gotchas.md +115 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/patterns.md +157 -0
- package/dist/template/.opencode/skill/cloudflare/references/turn/README.md +699 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/configuration.md +19 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/gotchas.md +27 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/patterns.md +41 -0
- package/dist/template/.opencode/skill/cloudflare/references/vectorize/README.md +682 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/configuration.md +44 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/gotchas.md +24 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/patterns.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/README.md +19 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/api.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/configuration.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/gotchas.md +28 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/patterns.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/README.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/api.md +199 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/configuration.md +185 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/gotchas.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/patterns.md +216 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/README.md +96 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/api.md +137 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/configuration.md +147 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/gotchas.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/patterns.md +149 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-ai/README.md +116 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/README.md +48 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/api.md +169 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/configuration.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/gotchas.md +130 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/patterns.md +170 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/api.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/configuration.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/gotchas.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-vpc/README.md +579 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/api.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/configuration.md +177 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/gotchas.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/patterns.md +132 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/README.md +90 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/api.md +140 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/configuration.md +128 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/gotchas.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/patterns.md +150 -0
- package/dist/template/.opencode/skill/cloudflare/references/zaraz/README.md +360 -0
- package/dist/template/.opencode/skill/react-best-practices/AGENTS.md +2410 -0
- package/dist/template/.opencode/skill/react-best-practices/README.md +123 -0
- package/dist/template/.opencode/skill/react-best-practices/SKILL.md +125 -0
- package/dist/template/.opencode/skill/react-best-practices/metadata.json +15 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/_sections.md +46 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/_template.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-api-routes.md +38 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-defer-await.md +80 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-dependencies.md +36 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-parallel.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-conditional.md +31 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-preload.md +50 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-event-listeners.md +74 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-storage.md +70 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-early-exit.md +50 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-index-maps.md +37 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-length-check-first.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-activity.md +26 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-memo.md +44 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-transitions.md +40 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-lru.md +41 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-react.md +76 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-serialization.md +38 -0
- package/dist/template/.opencode/skill/supabase/SKILL.md +120 -0
- package/dist/template/.opencode/skill/supabase/mcp.json +27 -0
- package/dist/template/.opencode/skill/vercel-deploy-claimable/SKILL.md +112 -0
- package/dist/template/.opencode/skill/vercel-deploy-claimable/scripts/deploy.sh +249 -0
- package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +39 -0
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# DDoS Configuration
|
|
2
|
+
|
|
3
|
+
## Dashboard Setup
|
|
4
|
+
|
|
5
|
+
1. Navigate to Security > DDoS
|
|
6
|
+
2. Select HTTP DDoS or Network-layer DDoS
|
|
7
|
+
3. Configure sensitivity & action per ruleset/category/rule
|
|
8
|
+
4. Apply overrides with optional expressions (Enterprise Advanced)
|
|
9
|
+
|
|
10
|
+
## Rule Structure
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
interface DDoSOverride {
|
|
14
|
+
description: string;
|
|
15
|
+
rules: Array<{
|
|
16
|
+
action: "execute";
|
|
17
|
+
expression: string; // Filter traffic, "true" for all
|
|
18
|
+
action_parameters: {
|
|
19
|
+
id: string; // Managed ruleset ID
|
|
20
|
+
overrides: {
|
|
21
|
+
sensitivity_level?: "default" | "medium" | "low" | "eoff";
|
|
22
|
+
action?: "block" | "managed_challenge" | "challenge" | "log";
|
|
23
|
+
categories?: Array<{ // Override by category
|
|
24
|
+
category: string; // e.g., "http-flood", "udp-flood"
|
|
25
|
+
sensitivity_level?: string;
|
|
26
|
+
}>;
|
|
27
|
+
rules?: Array<{ // Override by rule ID
|
|
28
|
+
id: string;
|
|
29
|
+
action?: string;
|
|
30
|
+
sensitivity_level?: string;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Sensitivity Mapping
|
|
39
|
+
|
|
40
|
+
| UI | API | Threshold |
|
|
41
|
+
|----|-----|-----------|
|
|
42
|
+
| High | `default` | Most aggressive |
|
|
43
|
+
| Medium | `medium` | Balanced |
|
|
44
|
+
| Low | `low` | Less aggressive |
|
|
45
|
+
| Essentially Off | `eoff` | Minimal mitigation |
|
|
46
|
+
|
|
47
|
+
## Common Categories
|
|
48
|
+
|
|
49
|
+
- `http-flood`, `http-anomaly` (L7)
|
|
50
|
+
- `udp-flood`, `syn-flood`, `dns-flood` (L3/4)
|
|
51
|
+
|
|
52
|
+
## Adaptive Rules
|
|
53
|
+
|
|
54
|
+
Configure by targeting specific rule IDs. Check dashboard for IDs:
|
|
55
|
+
- HTTP: origins, user-agents, locations
|
|
56
|
+
- L4: protocols
|
|
57
|
+
|
|
58
|
+
Requires 7 days of traffic history to learn baseline.
|
|
59
|
+
|
|
60
|
+
## Alerting
|
|
61
|
+
|
|
62
|
+
Configure via Notifications:
|
|
63
|
+
- Alert types: `http_ddos_attack_alert`, `layer_3_4_ddos_attack_alert`, `advanced_*` variants
|
|
64
|
+
- Filters: zones, hostnames, RPS/PPS/Mbps thresholds, IPs, protocols
|
|
65
|
+
- Mechanisms: email, webhooks, PagerDuty
|
|
66
|
+
|
|
67
|
+
See [api.md](./api.md#alert-configuration) for API examples.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# DDoS Gotchas
|
|
2
|
+
|
|
3
|
+
## False Positives
|
|
4
|
+
|
|
5
|
+
**Symptom**: Legitimate traffic blocked/challenged
|
|
6
|
+
|
|
7
|
+
**Diagnosis**:
|
|
8
|
+
```typescript
|
|
9
|
+
// Query GraphQL API for flagged requests
|
|
10
|
+
const query = `
|
|
11
|
+
query {
|
|
12
|
+
viewer {
|
|
13
|
+
zones(filter: { zoneTag: "${zoneId}" }) {
|
|
14
|
+
httpRequestsAdaptiveGroups(
|
|
15
|
+
filter: { ruleId: "${ruleId}", action: "log" }
|
|
16
|
+
limit: 100
|
|
17
|
+
orderBy: [datetime_DESC]
|
|
18
|
+
) {
|
|
19
|
+
dimensions {
|
|
20
|
+
clientCountryName
|
|
21
|
+
clientRequestHTTPHost
|
|
22
|
+
clientRequestPath
|
|
23
|
+
userAgent
|
|
24
|
+
}
|
|
25
|
+
count
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Fix**:
|
|
34
|
+
1. Lower sensitivity for specific rule/category
|
|
35
|
+
2. Use `log` action first to validate (Enterprise Advanced)
|
|
36
|
+
3. Add exception with custom expression (e.g., allowlist IPs)
|
|
37
|
+
4. Reduce category sensitivity: `{ category: "http-flood", sensitivity_level: "low" }`
|
|
38
|
+
|
|
39
|
+
## Attacks Getting Through
|
|
40
|
+
|
|
41
|
+
**Cause**: Sensitivity too low, wrong action
|
|
42
|
+
|
|
43
|
+
**Fix**:
|
|
44
|
+
```typescript
|
|
45
|
+
// Increase to default (high) sensitivity
|
|
46
|
+
const config = {
|
|
47
|
+
rules: [{
|
|
48
|
+
expression: "true",
|
|
49
|
+
action: "execute",
|
|
50
|
+
action_parameters: {
|
|
51
|
+
id: managedRulesetId,
|
|
52
|
+
overrides: { sensitivity_level: "default", action: "block" },
|
|
53
|
+
},
|
|
54
|
+
}],
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Adaptive Rules Not Working
|
|
59
|
+
|
|
60
|
+
**Cause**: Insufficient traffic history (needs 7 days)
|
|
61
|
+
|
|
62
|
+
**Fix**: Wait for baseline to establish, check dashboard for adaptive rule status
|
|
63
|
+
|
|
64
|
+
## Zone vs Account Override Conflict
|
|
65
|
+
|
|
66
|
+
**Issue**: Account overrides ignored when zone has overrides
|
|
67
|
+
|
|
68
|
+
**Solution**: Configure at zone level OR remove zone overrides to use account-level
|
|
69
|
+
|
|
70
|
+
## Log Action Not Available
|
|
71
|
+
|
|
72
|
+
**Cause**: Not on Enterprise Advanced DDoS plan
|
|
73
|
+
|
|
74
|
+
**Workaround**: Use `managed_challenge` with low sensitivity for testing
|
|
75
|
+
|
|
76
|
+
## Rule Limit Exceeded
|
|
77
|
+
|
|
78
|
+
**Plans**:
|
|
79
|
+
- Free/Pro/Business: 1 override rule only
|
|
80
|
+
- Enterprise Advanced: Up to 10 rules
|
|
81
|
+
|
|
82
|
+
**Workaround**: Combine conditions in single expression using `and`/`or`
|
|
83
|
+
|
|
84
|
+
## Read-only Managed Rules
|
|
85
|
+
|
|
86
|
+
**Issue**: Some rules cannot be overridden
|
|
87
|
+
|
|
88
|
+
**Check**: API response indicates if rule is read-only
|
|
89
|
+
|
|
90
|
+
## Always-on Protection
|
|
91
|
+
|
|
92
|
+
**Reality**: DDoS managed rulesets cannot be fully disabled
|
|
93
|
+
|
|
94
|
+
**Minimum**: Set `sensitivity_level: "eoff"` for minimal mitigation
|
|
95
|
+
|
|
96
|
+
## Tuning Strategy
|
|
97
|
+
|
|
98
|
+
1. Start with `log` action + `medium` sensitivity
|
|
99
|
+
2. Monitor for 24-48 hours
|
|
100
|
+
3. Identify false positives, add exceptions
|
|
101
|
+
4. Gradually increase to `default` sensitivity
|
|
102
|
+
5. Change action from `log` → `managed_challenge` → `block`
|
|
103
|
+
6. Document all adjustments
|
|
104
|
+
|
|
105
|
+
## Best Practices
|
|
106
|
+
|
|
107
|
+
- Test during low-traffic periods
|
|
108
|
+
- Use zone-level for per-site tuning
|
|
109
|
+
- Reference IP lists for easier management
|
|
110
|
+
- Set appropriate alert thresholds (avoid noise)
|
|
111
|
+
- Combine with WAF for layered defense
|
|
112
|
+
- Avoid over-tuning (keep config simple)
|
|
113
|
+
|
|
114
|
+
See [patterns.md](./patterns.md) for progressive rollout examples.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# DDoS Protection Patterns
|
|
2
|
+
|
|
3
|
+
## Allowlist Trusted IPs
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// Account-level override with custom expression
|
|
7
|
+
const config = {
|
|
8
|
+
description: "Allowlist trusted IPs",
|
|
9
|
+
rules: [{
|
|
10
|
+
expression: "ip.src in { 203.0.113.0/24 192.0.2.1 }",
|
|
11
|
+
action: "execute",
|
|
12
|
+
action_parameters: {
|
|
13
|
+
id: managedRulesetId,
|
|
14
|
+
overrides: { sensitivity_level: "eoff" }, // Effectively off
|
|
15
|
+
},
|
|
16
|
+
}],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
await fetch(
|
|
20
|
+
`https://api.cloudflare.com/client/v4/accounts/${accountId}/rulesets/phases/ddos_l7/entrypoint`,
|
|
21
|
+
{ method: "PUT", headers: { Authorization: `Bearer ${apiToken}`, "Content-Type": "application/json" }, body: JSON.stringify(config) }
|
|
22
|
+
);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Route-specific Sensitivity
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// Lower sensitivity for bursty API endpoints
|
|
29
|
+
const config = {
|
|
30
|
+
description: "Route-specific protection",
|
|
31
|
+
rules: [
|
|
32
|
+
{
|
|
33
|
+
expression: "not http.request.uri.path matches \"^/api/\"",
|
|
34
|
+
action: "execute",
|
|
35
|
+
action_parameters: {
|
|
36
|
+
id: managedRulesetId,
|
|
37
|
+
overrides: { sensitivity_level: "default", action: "block" },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
expression: "http.request.uri.path matches \"^/api/\"",
|
|
42
|
+
action: "execute",
|
|
43
|
+
action_parameters: {
|
|
44
|
+
id: managedRulesetId,
|
|
45
|
+
overrides: { sensitivity_level: "low", action: "managed_challenge" },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Progressive Enhancement
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
enum ProtectionLevel { MONITORING = "monitoring", LOW = "low", MEDIUM = "medium", HIGH = "high" }
|
|
56
|
+
|
|
57
|
+
async function setProtectionLevel(zoneId: string, level: ProtectionLevel, managedRulesetId: string, apiToken: string) {
|
|
58
|
+
const levelConfig = {
|
|
59
|
+
[ProtectionLevel.MONITORING]: { action: "log", sensitivity: "eoff" },
|
|
60
|
+
[ProtectionLevel.LOW]: { action: "managed_challenge", sensitivity: "low" },
|
|
61
|
+
[ProtectionLevel.MEDIUM]: { action: "managed_challenge", sensitivity: "medium" },
|
|
62
|
+
[ProtectionLevel.HIGH]: { action: "block", sensitivity: "default" },
|
|
63
|
+
} as const;
|
|
64
|
+
|
|
65
|
+
const settings = levelConfig[level];
|
|
66
|
+
const config = {
|
|
67
|
+
description: `DDoS protection level: ${level}`,
|
|
68
|
+
rules: [{
|
|
69
|
+
expression: "true",
|
|
70
|
+
action: "execute",
|
|
71
|
+
action_parameters: {
|
|
72
|
+
id: managedRulesetId,
|
|
73
|
+
overrides: { action: settings.action, sensitivity_level: settings.sensitivity },
|
|
74
|
+
},
|
|
75
|
+
}],
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return fetch(/* ... */);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Gradual rollout: Week 1 MONITORING → Week 2 LOW → Week 3 MEDIUM → Week 4 HIGH
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Dynamic Response to Attacks
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Worker adjusts settings based on attack patterns
|
|
88
|
+
interface Env {
|
|
89
|
+
CLOUDFLARE_API_TOKEN: string;
|
|
90
|
+
ZONE_ID: string;
|
|
91
|
+
KV_NAMESPACE: KVNamespace;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default {
|
|
95
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
96
|
+
if (request.url.includes("/attack-detected")) {
|
|
97
|
+
const attackData = await request.json();
|
|
98
|
+
await env.KV_NAMESPACE.put(`attack:${Date.now()}`, JSON.stringify(attackData), { expirationTtl: 86400 });
|
|
99
|
+
|
|
100
|
+
const recentAttacks = await getRecentAttacks(env.KV_NAMESPACE);
|
|
101
|
+
if (recentAttacks.length > 5) {
|
|
102
|
+
await increaseProtection(env.ZONE_ID, "managed-ruleset-id", env.CLOUDFLARE_API_TOKEN);
|
|
103
|
+
return new Response("Protection increased", { status: 200 });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return new Response("OK");
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
// Cron: auto-decrease after quiet period
|
|
110
|
+
async scheduled(event: ScheduledEvent, env: Env): Promise<void> {
|
|
111
|
+
const recentAttacks = await getRecentAttacks(env.KV_NAMESPACE);
|
|
112
|
+
if (recentAttacks.length === 0) {
|
|
113
|
+
await normalizeProtection(env.ZONE_ID, "managed-ruleset-id", env.CLOUDFLARE_API_TOKEN);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Multi-rule Tiered Protection (Enterprise Advanced)
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// Up to 10 rules with different conditions
|
|
123
|
+
const config = {
|
|
124
|
+
description: "Multi-tier DDoS protection",
|
|
125
|
+
rules: [
|
|
126
|
+
{ // Strictest for unknown traffic
|
|
127
|
+
expression: "not ip.src in $known_ips and not cf.bot_management.score gt 30",
|
|
128
|
+
action: "execute",
|
|
129
|
+
action_parameters: {
|
|
130
|
+
id: managedRulesetId,
|
|
131
|
+
overrides: { sensitivity_level: "default", action: "block" },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
{ // Medium for verified bots
|
|
135
|
+
expression: "cf.bot_management.verified_bot",
|
|
136
|
+
action: "execute",
|
|
137
|
+
action_parameters: {
|
|
138
|
+
id: managedRulesetId,
|
|
139
|
+
overrides: { sensitivity_level: "medium", action: "managed_challenge" },
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{ // Low for trusted IPs
|
|
143
|
+
expression: "ip.src in $trusted_ips",
|
|
144
|
+
action: "execute",
|
|
145
|
+
action_parameters: {
|
|
146
|
+
id: managedRulesetId,
|
|
147
|
+
overrides: { sensitivity_level: "low" },
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Defense in Depth
|
|
155
|
+
|
|
156
|
+
Combine DDoS with WAF, Rate Limiting, Bot Management. Layer protections at different levels.
|
|
157
|
+
|
|
158
|
+
See [configuration.md](./configuration.md) for rule structure details.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Cloudflare Durable Objects Storage
|
|
2
|
+
|
|
3
|
+
Persistent storage API for Durable Objects with SQLite and KV backends, PITR, and automatic concurrency control.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
DO Storage provides:
|
|
8
|
+
- SQLite-backed (recommended) or KV-backed
|
|
9
|
+
- SQL API + synchronous/async KV APIs
|
|
10
|
+
- Automatic input/output gates (race-free)
|
|
11
|
+
- 30-day point-in-time recovery (PITR)
|
|
12
|
+
- Transactions and alarms
|
|
13
|
+
|
|
14
|
+
**Use cases:** Stateful coordination, real-time collaboration, counters, sessions, rate limiters
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
export class Counter extends DurableObject {
|
|
20
|
+
sql: SqlStorage;
|
|
21
|
+
|
|
22
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
23
|
+
super(ctx, env);
|
|
24
|
+
this.sql = ctx.storage.sql;
|
|
25
|
+
this.sql.exec('CREATE TABLE IF NOT EXISTS data(key TEXT PRIMARY KEY, value INTEGER)');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async increment(): Promise<number> {
|
|
29
|
+
this.sql.exec('INSERT OR REPLACE INTO data VALUES (?, ?) RETURNING value', 'counter',
|
|
30
|
+
(this.sql.exec('SELECT value FROM data WHERE key = ?', 'counter').one()?.value || 0) + 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Storage Backends
|
|
36
|
+
|
|
37
|
+
| Backend | Create Method | APIs | PITR |
|
|
38
|
+
|---------|---------------|------|------|
|
|
39
|
+
| SQLite (recommended) | `new_sqlite_classes` | SQL + sync KV + async KV | ✅ |
|
|
40
|
+
| KV (legacy) | `new_classes` | async KV only | ❌ |
|
|
41
|
+
|
|
42
|
+
## Core APIs
|
|
43
|
+
|
|
44
|
+
- **SQL API** (`ctx.storage.sql`): Full SQLite with extensions (FTS5, JSON, math)
|
|
45
|
+
- **Sync KV** (`ctx.storage.kv`): Synchronous key-value (SQLite only)
|
|
46
|
+
- **Async KV** (`ctx.storage`): Asynchronous key-value (both backends)
|
|
47
|
+
- **Transactions** (`transactionSync()`, `transaction()`)
|
|
48
|
+
- **PITR** (`getBookmarkForTime()`, `onNextSessionRestoreBookmark()`)
|
|
49
|
+
- **Alarms** (`setAlarm()`, `alarm()` handler)
|
|
50
|
+
|
|
51
|
+
## In This Reference
|
|
52
|
+
|
|
53
|
+
- [configuration.md](./configuration.md) - wrangler.jsonc migrations, SQLite vs KV setup
|
|
54
|
+
- [api.md](./api.md) - SQL exec/cursors, KV methods, transactions, alarms, PITR
|
|
55
|
+
- [patterns.md](./patterns.md) - Schema migrations, caching, rate limiting, batch processing
|
|
56
|
+
- [gotchas.md](./gotchas.md) - Concurrency gates, transaction rules, SQL limits, async pitfalls
|
|
57
|
+
|
|
58
|
+
## See Also
|
|
59
|
+
|
|
60
|
+
- [durable-objects](../durable-objects/) - DO fundamentals and coordination patterns
|
|
61
|
+
- [workers](../workers/) - Worker runtime for DO stubs
|
|
62
|
+
- [d1](../d1/) - Shared database alternative to per-DO storage
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# DO Storage API Reference
|
|
2
|
+
|
|
3
|
+
## SQL API
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
const cursor = this.sql.exec('SELECT * FROM users WHERE email = ?', email);
|
|
7
|
+
for (let row of cursor) {} // Objects: { id, name, email }
|
|
8
|
+
cursor.toArray(); cursor.one(); // Single row (throws if != 1)
|
|
9
|
+
for (let row of cursor.raw()) {} // Arrays: [1, "Alice", "..."]
|
|
10
|
+
cursor.columnNames; // ["id", "name", "email"]
|
|
11
|
+
cursor.rowsRead; cursor.rowsWritten; // Billing
|
|
12
|
+
|
|
13
|
+
type User = { id: number; name: string; email: string };
|
|
14
|
+
const user = this.sql.exec<User>('...', userId).one();
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Sync KV API (SQLite only)
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
this.ctx.storage.kv.get("counter"); // undefined if missing
|
|
21
|
+
this.ctx.storage.kv.put("counter", 42);
|
|
22
|
+
this.ctx.storage.kv.put("user", { name: "Alice", age: 30 });
|
|
23
|
+
this.ctx.storage.kv.delete("counter"); // true if existed
|
|
24
|
+
|
|
25
|
+
for (let [key, value] of this.ctx.storage.kv.list()) {}
|
|
26
|
+
|
|
27
|
+
// List options: start, prefix, reverse, limit
|
|
28
|
+
this.ctx.storage.kv.list({ start: "user:", prefix: "user:", reverse: true, limit: 100 });
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Async KV API (Both backends)
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
await this.ctx.storage.get("key"); // Single
|
|
35
|
+
await this.ctx.storage.get(["key1", "key2"]); // Multiple (max 128)
|
|
36
|
+
await this.ctx.storage.put("key", value); // Single
|
|
37
|
+
await this.ctx.storage.put({ "key1": "v1", "key2": { nested: true } }); // Multiple (max 128)
|
|
38
|
+
await this.ctx.storage.delete("key");
|
|
39
|
+
await this.ctx.storage.delete(["key1", "key2"]);
|
|
40
|
+
await this.ctx.storage.list({ prefix: "user:", limit: 100 });
|
|
41
|
+
|
|
42
|
+
// Options: allowConcurrency, noCache, allowUnconfirmed
|
|
43
|
+
await this.ctx.storage.get("key", { allowConcurrency: true, noCache: true });
|
|
44
|
+
await this.ctx.storage.put("key", value, { allowUnconfirmed: true, noCache: true });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Transactions
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Sync (SQL/sync KV only)
|
|
51
|
+
this.ctx.storage.transactionSync(() => {
|
|
52
|
+
this.sql.exec('UPDATE accounts SET balance = balance - ? WHERE id = ?', 100, 1);
|
|
53
|
+
this.sql.exec('UPDATE accounts SET balance = balance + ? WHERE id = ?', 100, 2);
|
|
54
|
+
return "result";
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Async
|
|
58
|
+
await this.ctx.storage.transaction(async () => {
|
|
59
|
+
const value = await this.ctx.storage.get("counter");
|
|
60
|
+
await this.ctx.storage.put("counter", value + 1);
|
|
61
|
+
if (value > 100) this.ctx.storage.rollback(); // Explicit rollback
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Point-in-Time Recovery
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
await this.ctx.storage.getCurrentBookmark();
|
|
69
|
+
await this.ctx.storage.getBookmarkForTime(Date.now() - 2 * 24 * 60 * 60 * 1000);
|
|
70
|
+
await this.ctx.storage.onNextSessionRestoreBookmark(bookmark);
|
|
71
|
+
this.ctx.abort(); // Restart to apply; bookmarks lexically comparable (earlier < later)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Alarms
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
await this.ctx.storage.setAlarm(Date.now() + 60000); // Timestamp or Date
|
|
78
|
+
await this.ctx.storage.getAlarm();
|
|
79
|
+
await this.ctx.storage.deleteAlarm();
|
|
80
|
+
|
|
81
|
+
async alarm() { await this.doScheduledWork(); }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Misc
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
await this.ctx.storage.deleteAll(); // Atomic for SQLite; alarm NOT included
|
|
88
|
+
this.ctx.storage.sql.databaseSize; // Bytes
|
|
89
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# DO Storage Configuration
|
|
2
|
+
|
|
3
|
+
## SQLite-backed (Recommended)
|
|
4
|
+
|
|
5
|
+
**wrangler.jsonc:**
|
|
6
|
+
```jsonc
|
|
7
|
+
{
|
|
8
|
+
"migrations": [
|
|
9
|
+
{
|
|
10
|
+
"tag": "v1",
|
|
11
|
+
"new_sqlite_classes": ["Counter", "Session", "RateLimiter"]
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**wrangler.toml:**
|
|
18
|
+
```toml
|
|
19
|
+
[[migrations]]
|
|
20
|
+
tag = "v1"
|
|
21
|
+
new_sqlite_classes = ["Counter", "Session"]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## KV-backed (Legacy)
|
|
25
|
+
|
|
26
|
+
**wrangler.jsonc:**
|
|
27
|
+
```jsonc
|
|
28
|
+
{
|
|
29
|
+
"migrations": [
|
|
30
|
+
{
|
|
31
|
+
"tag": "v1",
|
|
32
|
+
"new_classes": ["OldCounter"]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## TypeScript Setup
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
export class MyDurableObject extends DurableObject {
|
|
42
|
+
sql: SqlStorage;
|
|
43
|
+
|
|
44
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
45
|
+
super(ctx, env);
|
|
46
|
+
this.sql = ctx.storage.sql;
|
|
47
|
+
|
|
48
|
+
// Initialize schema
|
|
49
|
+
this.sql.exec(`
|
|
50
|
+
CREATE TABLE IF NOT EXISTS users(
|
|
51
|
+
id INTEGER PRIMARY KEY,
|
|
52
|
+
name TEXT NOT NULL,
|
|
53
|
+
email TEXT UNIQUE
|
|
54
|
+
);
|
|
55
|
+
`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Binding
|
|
60
|
+
interface Env {
|
|
61
|
+
MY_DO: DurableObjectNamespace;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default {
|
|
65
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
66
|
+
const id = env.MY_DO.idFromName('singleton');
|
|
67
|
+
const stub = env.MY_DO.get(id);
|
|
68
|
+
return stub.fetch(request);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## CPU Limits
|
|
74
|
+
|
|
75
|
+
```jsonc
|
|
76
|
+
{
|
|
77
|
+
"limits": {
|
|
78
|
+
"cpu_ms": 300000 // 5 minutes (default 30s)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```toml
|
|
84
|
+
[limits]
|
|
85
|
+
cpu_ms = 300_000
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Location Control
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Jurisdiction (GDPR/FedRAMP)
|
|
92
|
+
const euNamespace = env.MY_DO.jurisdiction("eu");
|
|
93
|
+
const id = euNamespace.newUniqueId();
|
|
94
|
+
const stub = euNamespace.get(id);
|
|
95
|
+
|
|
96
|
+
// Location hint (best effort)
|
|
97
|
+
const stub = env.MY_DO.get(id, { locationHint: "enam" });
|
|
98
|
+
// Hints: wnam, enam, sam, weur, eeur, apac, oc, afr, me
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Initialization
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
export class Counter extends DurableObject {
|
|
105
|
+
value: number;
|
|
106
|
+
|
|
107
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
108
|
+
super(ctx, env);
|
|
109
|
+
|
|
110
|
+
// Block concurrent requests during init
|
|
111
|
+
ctx.blockConcurrencyWhile(async () => {
|
|
112
|
+
this.value = (await ctx.storage.get("value")) || 0;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# DO Storage Gotchas & Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Concurrency Gates
|
|
4
|
+
|
|
5
|
+
**Input gate:** No new events while storage op pending (except storage completions)
|
|
6
|
+
**Output gate:** Network messages held until storage writes confirm
|
|
7
|
+
|
|
8
|
+
```typescript
|
|
9
|
+
// ✅ NO RACE: Auto serialization
|
|
10
|
+
async getUniqueNumber() {
|
|
11
|
+
let val = await this.ctx.storage.get("counter"); // Other requests blocked
|
|
12
|
+
await this.ctx.storage.put("counter", val + 1);
|
|
13
|
+
return val;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ❌ RACE: Concurrent calls from same event
|
|
17
|
+
async handler() {
|
|
18
|
+
const [v1, v2] = await Promise.all([this.getUniqueNumber(), this.getUniqueNumber()]); // v1 === v2!
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ✅ SAFE: Response waits for write confirm; if write fails, response discarded & restart
|
|
22
|
+
async increment() {
|
|
23
|
+
let val = await this.ctx.storage.get("counter");
|
|
24
|
+
this.ctx.storage.put("counter", val + 1); // Don't await
|
|
25
|
+
return new Response(String(val));
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Transaction Rules
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
// ❌ WRONG: Direct SQL statements
|
|
33
|
+
this.sql.exec('BEGIN TRANSACTION');
|
|
34
|
+
|
|
35
|
+
// ✅ CORRECT: Use transactionSync() or async transaction()
|
|
36
|
+
this.ctx.storage.transactionSync(() => { this.sql.exec('UPDATE ...'); });
|
|
37
|
+
await this.ctx.storage.transaction(async () => { await this.ctx.storage.put("key", value); });
|
|
38
|
+
|
|
39
|
+
// ❌ WRONG: Async in transactionSync
|
|
40
|
+
this.ctx.storage.transactionSync(async () => { await fetch(...); }); // Error!
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Limits
|
|
44
|
+
|
|
45
|
+
**SQL:** Max cols/table: 100; string/BLOB/row: 2MB; statement: 100KB; params: 100; LIKE/GLOB: 50B
|
|
46
|
+
**Storage:** SQLite: 10GB/object, 2MB key+value; KV: Unlimited storage, key 2KiB, value 128KiB
|
|
47
|
+
|
|
48
|
+
## TypeScript Type Safety
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// ❌ Types don't validate at runtime
|
|
52
|
+
type User = { id: number; name: string };
|
|
53
|
+
const user = this.sql.exec<User>('SELECT id FROM users WHERE id = ?', id).one(); // Only has { id }!
|
|
54
|
+
|
|
55
|
+
// ✅ Query must match type
|
|
56
|
+
const user = this.sql.exec<User>('SELECT id, name FROM users WHERE id = ?', id).one();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Alarm Persistence
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// ❌ deleteAll() doesn't delete alarms
|
|
63
|
+
await this.ctx.storage.deleteAll(); // Alarm remains!
|
|
64
|
+
|
|
65
|
+
// ✅ Delete alarm explicitly
|
|
66
|
+
await this.ctx.storage.deleteAlarm();
|
|
67
|
+
await this.ctx.storage.deleteAll();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Auto Caching & Bypass
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Built-in cache makes simple code fast
|
|
74
|
+
async getUniqueNumber() {
|
|
75
|
+
let val = await this.ctx.storage.get("counter"); // Cached after first
|
|
76
|
+
await this.ctx.storage.put("counter", val + 1); // Instant cache write
|
|
77
|
+
return val;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Bypass opts: allowConcurrency, noCache, allowUnconfirmed
|
|
81
|
+
await this.ctx.storage.get("key", { allowConcurrency: true, noCache: true });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Common Errors & Best Practices
|
|
85
|
+
|
|
86
|
+
**Slow perf:** Use sync KV API (`ctx.storage.kv`) vs async
|
|
87
|
+
**Races:** Check concurrent calls from same event (not protected)
|
|
88
|
+
**High billing:** Check `rowsRead`/`rowsWritten`; verify unused objects call `deleteAll()`
|
|
89
|
+
**Overload:** Single DO soft limit ~1K req/sec; shard
|
|
90
|
+
|
|
91
|
+
**Do:** Use SQLite-backed; sync KV for simple key-value; don't await writes unnecessarily (output gate protects); use `blockConcurrencyWhile()` for init; delete alarms AND storage when cleaning
|
|
92
|
+
|
|
93
|
+
**Don't:** Use SQL transaction statements directly; initiate concurrent storage ops from same event; assume TypeScript types validate at runtime
|