pi-cloudflare 0.1.0
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/LICENSE +674 -0
- package/README.md +67 -0
- package/bin/setup.mjs +103 -0
- package/dist/auth-flow.d.ts +15 -0
- package/dist/auth-flow.d.ts.map +1 -0
- package/dist/auth-flow.js +90 -0
- package/dist/auth-flow.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +47 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +44 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +135 -0
- package/dist/oauth.js.map +1 -0
- package/dist/proxy.d.ts +29 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +39 -0
- package/dist/proxy.js.map +1 -0
- package/dist/servers.d.ts +19 -0
- package/dist/servers.d.ts.map +1 -0
- package/dist/servers.js +40 -0
- package/dist/servers.js.map +1 -0
- package/dist/token-store.d.ts +23 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +47 -0
- package/dist/token-store.js.map +1 -0
- package/package.json +67 -0
- package/skills/agents-sdk/SKILL.md +221 -0
- package/skills/agents-sdk/references/browse-the-web.md +63 -0
- package/skills/agents-sdk/references/callable.md +92 -0
- package/skills/agents-sdk/references/client-sdk.md +110 -0
- package/skills/agents-sdk/references/codemode.md +110 -0
- package/skills/agents-sdk/references/configuration.md +72 -0
- package/skills/agents-sdk/references/durable-execution.md +51 -0
- package/skills/agents-sdk/references/email.md +146 -0
- package/skills/agents-sdk/references/human-in-the-loop.md +67 -0
- package/skills/agents-sdk/references/mcp.md +188 -0
- package/skills/agents-sdk/references/observability.md +44 -0
- package/skills/agents-sdk/references/queue-retries.md +79 -0
- package/skills/agents-sdk/references/routing.md +75 -0
- package/skills/agents-sdk/references/server-driven-messages.md +63 -0
- package/skills/agents-sdk/references/state-scheduling.md +171 -0
- package/skills/agents-sdk/references/streaming-chat.md +198 -0
- package/skills/agents-sdk/references/think.md +112 -0
- package/skills/agents-sdk/references/voice.md +68 -0
- package/skills/agents-sdk/references/webhooks-push.md +86 -0
- package/skills/agents-sdk/references/workflows.md +132 -0
- package/skills/cloudflare/SKILL.md +248 -0
- package/skills/cloudflare/references/agents-sdk/README.md +89 -0
- package/skills/cloudflare/references/agents-sdk/api.md +190 -0
- package/skills/cloudflare/references/agents-sdk/configuration.md +182 -0
- package/skills/cloudflare/references/agents-sdk/gotchas.md +158 -0
- package/skills/cloudflare/references/agents-sdk/patterns.md +192 -0
- package/skills/cloudflare/references/ai-gateway/README.md +175 -0
- package/skills/cloudflare/references/ai-gateway/configuration.md +111 -0
- package/skills/cloudflare/references/ai-gateway/dynamic-routing.md +82 -0
- package/skills/cloudflare/references/ai-gateway/features.md +96 -0
- package/skills/cloudflare/references/ai-gateway/sdk-integration.md +114 -0
- package/skills/cloudflare/references/ai-gateway/troubleshooting.md +88 -0
- package/skills/cloudflare/references/ai-search/README.md +138 -0
- package/skills/cloudflare/references/ai-search/api.md +87 -0
- package/skills/cloudflare/references/ai-search/configuration.md +88 -0
- package/skills/cloudflare/references/ai-search/gotchas.md +81 -0
- package/skills/cloudflare/references/ai-search/patterns.md +85 -0
- package/skills/cloudflare/references/analytics-engine/README.md +94 -0
- package/skills/cloudflare/references/analytics-engine/api.md +112 -0
- package/skills/cloudflare/references/analytics-engine/configuration.md +112 -0
- package/skills/cloudflare/references/analytics-engine/gotchas.md +85 -0
- package/skills/cloudflare/references/analytics-engine/patterns.md +83 -0
- package/skills/cloudflare/references/api/README.md +66 -0
- package/skills/cloudflare/references/api/api.md +204 -0
- package/skills/cloudflare/references/api/configuration.md +160 -0
- package/skills/cloudflare/references/api/gotchas.md +225 -0
- package/skills/cloudflare/references/api/patterns.md +204 -0
- package/skills/cloudflare/references/api-shield/README.md +44 -0
- package/skills/cloudflare/references/api-shield/api.md +141 -0
- package/skills/cloudflare/references/api-shield/configuration.md +192 -0
- package/skills/cloudflare/references/api-shield/gotchas.md +125 -0
- package/skills/cloudflare/references/api-shield/patterns.md +180 -0
- package/skills/cloudflare/references/argo-smart-routing/README.md +90 -0
- package/skills/cloudflare/references/argo-smart-routing/api.md +240 -0
- package/skills/cloudflare/references/argo-smart-routing/configuration.md +197 -0
- package/skills/cloudflare/references/argo-smart-routing/gotchas.md +111 -0
- package/skills/cloudflare/references/argo-smart-routing/patterns.md +104 -0
- package/skills/cloudflare/references/artifacts/README.md +79 -0
- package/skills/cloudflare/references/artifacts/api.md +128 -0
- package/skills/cloudflare/references/artifacts/configuration.md +92 -0
- package/skills/cloudflare/references/bindings/README.md +122 -0
- package/skills/cloudflare/references/bindings/api.md +203 -0
- package/skills/cloudflare/references/bindings/configuration.md +188 -0
- package/skills/cloudflare/references/bindings/gotchas.md +208 -0
- package/skills/cloudflare/references/bindings/patterns.md +200 -0
- package/skills/cloudflare/references/bot-management/README.md +94 -0
- package/skills/cloudflare/references/bot-management/api.md +169 -0
- package/skills/cloudflare/references/bot-management/configuration.md +163 -0
- package/skills/cloudflare/references/bot-management/gotchas.md +114 -0
- package/skills/cloudflare/references/bot-management/patterns.md +182 -0
- package/skills/cloudflare/references/browser-rendering/README.md +78 -0
- package/skills/cloudflare/references/browser-rendering/api.md +108 -0
- package/skills/cloudflare/references/browser-rendering/configuration.md +78 -0
- package/skills/cloudflare/references/browser-rendering/gotchas.md +88 -0
- package/skills/cloudflare/references/browser-rendering/patterns.md +91 -0
- package/skills/cloudflare/references/c3/README.md +111 -0
- package/skills/cloudflare/references/c3/api.md +71 -0
- package/skills/cloudflare/references/c3/configuration.md +81 -0
- package/skills/cloudflare/references/c3/gotchas.md +92 -0
- package/skills/cloudflare/references/c3/patterns.md +82 -0
- package/skills/cloudflare/references/cache-reserve/README.md +147 -0
- package/skills/cloudflare/references/cache-reserve/api.md +194 -0
- package/skills/cloudflare/references/cache-reserve/configuration.md +169 -0
- package/skills/cloudflare/references/cache-reserve/gotchas.md +132 -0
- package/skills/cloudflare/references/cache-reserve/patterns.md +197 -0
- package/skills/cloudflare/references/containers/README.md +85 -0
- package/skills/cloudflare/references/containers/api.md +187 -0
- package/skills/cloudflare/references/containers/configuration.md +188 -0
- package/skills/cloudflare/references/containers/gotchas.md +178 -0
- package/skills/cloudflare/references/containers/patterns.md +202 -0
- package/skills/cloudflare/references/cron-triggers/README.md +99 -0
- package/skills/cloudflare/references/cron-triggers/api.md +196 -0
- package/skills/cloudflare/references/cron-triggers/configuration.md +180 -0
- package/skills/cloudflare/references/cron-triggers/gotchas.md +199 -0
- package/skills/cloudflare/references/cron-triggers/patterns.md +190 -0
- package/skills/cloudflare/references/d1/README.md +133 -0
- package/skills/cloudflare/references/d1/api.md +196 -0
- package/skills/cloudflare/references/d1/configuration.md +191 -0
- package/skills/cloudflare/references/d1/gotchas.md +98 -0
- package/skills/cloudflare/references/d1/patterns.md +189 -0
- package/skills/cloudflare/references/ddos/README.md +41 -0
- package/skills/cloudflare/references/ddos/api.md +164 -0
- package/skills/cloudflare/references/ddos/configuration.md +93 -0
- package/skills/cloudflare/references/ddos/gotchas.md +107 -0
- package/skills/cloudflare/references/ddos/patterns.md +174 -0
- package/skills/cloudflare/references/do-storage/README.md +75 -0
- package/skills/cloudflare/references/do-storage/api.md +102 -0
- package/skills/cloudflare/references/do-storage/configuration.md +112 -0
- package/skills/cloudflare/references/do-storage/gotchas.md +150 -0
- package/skills/cloudflare/references/do-storage/patterns.md +194 -0
- package/skills/cloudflare/references/do-storage/testing.md +183 -0
- package/skills/cloudflare/references/durable-objects/README.md +185 -0
- package/skills/cloudflare/references/durable-objects/api.md +187 -0
- package/skills/cloudflare/references/durable-objects/configuration.md +160 -0
- package/skills/cloudflare/references/durable-objects/gotchas.md +197 -0
- package/skills/cloudflare/references/durable-objects/patterns.md +201 -0
- package/skills/cloudflare/references/email-routing/README.md +89 -0
- package/skills/cloudflare/references/email-routing/api.md +195 -0
- package/skills/cloudflare/references/email-routing/configuration.md +186 -0
- package/skills/cloudflare/references/email-routing/gotchas.md +196 -0
- package/skills/cloudflare/references/email-routing/patterns.md +229 -0
- package/skills/cloudflare/references/email-workers/README.md +151 -0
- package/skills/cloudflare/references/email-workers/api.md +237 -0
- package/skills/cloudflare/references/email-workers/configuration.md +112 -0
- package/skills/cloudflare/references/email-workers/gotchas.md +125 -0
- package/skills/cloudflare/references/email-workers/patterns.md +102 -0
- package/skills/cloudflare/references/flagship/README.md +59 -0
- package/skills/cloudflare/references/flagship/api.md +390 -0
- package/skills/cloudflare/references/flagship/configuration.md +202 -0
- package/skills/cloudflare/references/flagship/gotchas.md +178 -0
- package/skills/cloudflare/references/flagship/patterns.md +469 -0
- package/skills/cloudflare/references/graphql-api/README.md +147 -0
- package/skills/cloudflare/references/graphql-api/api.md +175 -0
- package/skills/cloudflare/references/graphql-api/configuration.md +118 -0
- package/skills/cloudflare/references/graphql-api/gotchas.md +110 -0
- package/skills/cloudflare/references/graphql-api/patterns.md +225 -0
- package/skills/cloudflare/references/hyperdrive/README.md +82 -0
- package/skills/cloudflare/references/hyperdrive/api.md +143 -0
- package/skills/cloudflare/references/hyperdrive/configuration.md +159 -0
- package/skills/cloudflare/references/hyperdrive/gotchas.md +77 -0
- package/skills/cloudflare/references/hyperdrive/patterns.md +190 -0
- package/skills/cloudflare/references/images/README.md +61 -0
- package/skills/cloudflare/references/images/api.md +96 -0
- package/skills/cloudflare/references/images/configuration.md +211 -0
- package/skills/cloudflare/references/images/gotchas.md +99 -0
- package/skills/cloudflare/references/images/patterns.md +115 -0
- package/skills/cloudflare/references/kv/README.md +89 -0
- package/skills/cloudflare/references/kv/api.md +160 -0
- package/skills/cloudflare/references/kv/configuration.md +144 -0
- package/skills/cloudflare/references/kv/gotchas.md +131 -0
- package/skills/cloudflare/references/kv/patterns.md +196 -0
- package/skills/cloudflare/references/miniflare/README.md +105 -0
- package/skills/cloudflare/references/miniflare/api.md +187 -0
- package/skills/cloudflare/references/miniflare/configuration.md +173 -0
- package/skills/cloudflare/references/miniflare/gotchas.md +160 -0
- package/skills/cloudflare/references/miniflare/patterns.md +181 -0
- package/skills/cloudflare/references/network-interconnect/README.md +99 -0
- package/skills/cloudflare/references/network-interconnect/api.md +199 -0
- package/skills/cloudflare/references/network-interconnect/configuration.md +114 -0
- package/skills/cloudflare/references/network-interconnect/gotchas.md +165 -0
- package/skills/cloudflare/references/network-interconnect/patterns.md +166 -0
- package/skills/cloudflare/references/observability/README.md +88 -0
- package/skills/cloudflare/references/observability/api.md +164 -0
- package/skills/cloudflare/references/observability/configuration.md +169 -0
- package/skills/cloudflare/references/observability/gotchas.md +115 -0
- package/skills/cloudflare/references/observability/patterns.md +105 -0
- package/skills/cloudflare/references/pages/README.md +88 -0
- package/skills/cloudflare/references/pages/api.md +204 -0
- package/skills/cloudflare/references/pages/configuration.md +201 -0
- package/skills/cloudflare/references/pages/gotchas.md +203 -0
- package/skills/cloudflare/references/pages/patterns.md +204 -0
- package/skills/cloudflare/references/pages-functions/README.md +98 -0
- package/skills/cloudflare/references/pages-functions/api.md +143 -0
- package/skills/cloudflare/references/pages-functions/configuration.md +122 -0
- package/skills/cloudflare/references/pages-functions/gotchas.md +94 -0
- package/skills/cloudflare/references/pages-functions/patterns.md +137 -0
- package/skills/cloudflare/references/pipelines/README.md +90 -0
- package/skills/cloudflare/references/pipelines/api.md +124 -0
- package/skills/cloudflare/references/pipelines/configuration.md +155 -0
- package/skills/cloudflare/references/pipelines/gotchas.md +58 -0
- package/skills/cloudflare/references/pipelines/patterns.md +130 -0
- package/skills/cloudflare/references/pulumi/README.md +100 -0
- package/skills/cloudflare/references/pulumi/api.md +200 -0
- package/skills/cloudflare/references/pulumi/configuration.md +198 -0
- package/skills/cloudflare/references/pulumi/gotchas.md +181 -0
- package/skills/cloudflare/references/pulumi/patterns.md +191 -0
- package/skills/cloudflare/references/queues/README.md +96 -0
- package/skills/cloudflare/references/queues/api.md +206 -0
- package/skills/cloudflare/references/queues/configuration.md +144 -0
- package/skills/cloudflare/references/queues/gotchas.md +206 -0
- package/skills/cloudflare/references/queues/patterns.md +220 -0
- package/skills/cloudflare/references/r2/README.md +95 -0
- package/skills/cloudflare/references/r2/api.md +200 -0
- package/skills/cloudflare/references/r2/configuration.md +165 -0
- package/skills/cloudflare/references/r2/gotchas.md +190 -0
- package/skills/cloudflare/references/r2/patterns.md +193 -0
- package/skills/cloudflare/references/r2-data-catalog/README.md +75 -0
- package/skills/cloudflare/references/r2-data-catalog/api.md +122 -0
- package/skills/cloudflare/references/r2-data-catalog/configuration.md +98 -0
- package/skills/cloudflare/references/r2-data-catalog/gotchas.md +55 -0
- package/skills/cloudflare/references/r2-data-catalog/patterns.md +122 -0
- package/skills/cloudflare/references/r2-sql/README.md +64 -0
- package/skills/cloudflare/references/r2-sql/api.md +121 -0
- package/skills/cloudflare/references/r2-sql/configuration.md +50 -0
- package/skills/cloudflare/references/r2-sql/gotchas.md +39 -0
- package/skills/cloudflare/references/r2-sql/patterns.md +118 -0
- package/skills/cloudflare/references/realtime-sfu/README.md +65 -0
- package/skills/cloudflare/references/realtime-sfu/api.md +158 -0
- package/skills/cloudflare/references/realtime-sfu/configuration.md +137 -0
- package/skills/cloudflare/references/realtime-sfu/gotchas.md +133 -0
- package/skills/cloudflare/references/realtime-sfu/patterns.md +174 -0
- package/skills/cloudflare/references/realtimekit/README.md +113 -0
- package/skills/cloudflare/references/realtimekit/api.md +212 -0
- package/skills/cloudflare/references/realtimekit/configuration.md +203 -0
- package/skills/cloudflare/references/realtimekit/gotchas.md +169 -0
- package/skills/cloudflare/references/realtimekit/patterns.md +223 -0
- package/skills/cloudflare/references/sandbox/README.md +96 -0
- package/skills/cloudflare/references/sandbox/api.md +198 -0
- package/skills/cloudflare/references/sandbox/configuration.md +143 -0
- package/skills/cloudflare/references/sandbox/gotchas.md +194 -0
- package/skills/cloudflare/references/sandbox/patterns.md +201 -0
- package/skills/cloudflare/references/secrets-store/README.md +74 -0
- package/skills/cloudflare/references/secrets-store/api.md +200 -0
- package/skills/cloudflare/references/secrets-store/configuration.md +185 -0
- package/skills/cloudflare/references/secrets-store/gotchas.md +97 -0
- package/skills/cloudflare/references/secrets-store/patterns.md +207 -0
- package/skills/cloudflare/references/smart-placement/README.md +138 -0
- package/skills/cloudflare/references/smart-placement/api.md +183 -0
- package/skills/cloudflare/references/smart-placement/configuration.md +196 -0
- package/skills/cloudflare/references/smart-placement/gotchas.md +174 -0
- package/skills/cloudflare/references/smart-placement/patterns.md +183 -0
- package/skills/cloudflare/references/snippets/README.md +68 -0
- package/skills/cloudflare/references/snippets/api.md +198 -0
- package/skills/cloudflare/references/snippets/configuration.md +227 -0
- package/skills/cloudflare/references/snippets/gotchas.md +86 -0
- package/skills/cloudflare/references/snippets/patterns.md +135 -0
- package/skills/cloudflare/references/spectrum/README.md +52 -0
- package/skills/cloudflare/references/spectrum/api.md +181 -0
- package/skills/cloudflare/references/spectrum/configuration.md +194 -0
- package/skills/cloudflare/references/spectrum/gotchas.md +145 -0
- package/skills/cloudflare/references/spectrum/patterns.md +196 -0
- package/skills/cloudflare/references/static-assets/README.md +65 -0
- package/skills/cloudflare/references/static-assets/api.md +199 -0
- package/skills/cloudflare/references/static-assets/configuration.md +186 -0
- package/skills/cloudflare/references/static-assets/gotchas.md +162 -0
- package/skills/cloudflare/references/static-assets/patterns.md +189 -0
- package/skills/cloudflare/references/stream/README.md +114 -0
- package/skills/cloudflare/references/stream/api-live.md +195 -0
- package/skills/cloudflare/references/stream/api.md +199 -0
- package/skills/cloudflare/references/stream/configuration.md +141 -0
- package/skills/cloudflare/references/stream/gotchas.md +130 -0
- package/skills/cloudflare/references/stream/patterns.md +184 -0
- package/skills/cloudflare/references/tail-workers/README.md +89 -0
- package/skills/cloudflare/references/tail-workers/api.md +200 -0
- package/skills/cloudflare/references/tail-workers/configuration.md +176 -0
- package/skills/cloudflare/references/tail-workers/gotchas.md +192 -0
- package/skills/cloudflare/references/tail-workers/patterns.md +180 -0
- package/skills/cloudflare/references/terraform/README.md +102 -0
- package/skills/cloudflare/references/terraform/api.md +178 -0
- package/skills/cloudflare/references/terraform/configuration.md +197 -0
- package/skills/cloudflare/references/terraform/gotchas.md +150 -0
- package/skills/cloudflare/references/terraform/patterns.md +174 -0
- package/skills/cloudflare/references/tunnel/README.md +129 -0
- package/skills/cloudflare/references/tunnel/api.md +193 -0
- package/skills/cloudflare/references/tunnel/configuration.md +157 -0
- package/skills/cloudflare/references/tunnel/gotchas.md +147 -0
- package/skills/cloudflare/references/tunnel/networking.md +168 -0
- package/skills/cloudflare/references/tunnel/patterns.md +192 -0
- package/skills/cloudflare/references/turn/README.md +82 -0
- package/skills/cloudflare/references/turn/api.md +239 -0
- package/skills/cloudflare/references/turn/configuration.md +179 -0
- package/skills/cloudflare/references/turn/gotchas.md +231 -0
- package/skills/cloudflare/references/turn/patterns.md +213 -0
- package/skills/cloudflare/references/turnstile/README.md +99 -0
- package/skills/cloudflare/references/turnstile/api.md +240 -0
- package/skills/cloudflare/references/turnstile/configuration.md +222 -0
- package/skills/cloudflare/references/turnstile/gotchas.md +218 -0
- package/skills/cloudflare/references/turnstile/patterns.md +193 -0
- package/skills/cloudflare/references/vectorize/README.md +133 -0
- package/skills/cloudflare/references/vectorize/api.md +88 -0
- package/skills/cloudflare/references/vectorize/configuration.md +88 -0
- package/skills/cloudflare/references/vectorize/gotchas.md +76 -0
- package/skills/cloudflare/references/vectorize/patterns.md +90 -0
- package/skills/cloudflare/references/waf/README.md +113 -0
- package/skills/cloudflare/references/waf/api.md +202 -0
- package/skills/cloudflare/references/waf/configuration.md +203 -0
- package/skills/cloudflare/references/waf/gotchas.md +204 -0
- package/skills/cloudflare/references/waf/patterns.md +197 -0
- package/skills/cloudflare/references/web-analytics/README.md +141 -0
- package/skills/cloudflare/references/web-analytics/configuration.md +76 -0
- package/skills/cloudflare/references/web-analytics/gotchas.md +82 -0
- package/skills/cloudflare/references/web-analytics/integration.md +60 -0
- package/skills/cloudflare/references/web-analytics/patterns.md +91 -0
- package/skills/cloudflare/references/workerd/README.md +78 -0
- package/skills/cloudflare/references/workerd/api.md +185 -0
- package/skills/cloudflare/references/workerd/configuration.md +183 -0
- package/skills/cloudflare/references/workerd/gotchas.md +139 -0
- package/skills/cloudflare/references/workerd/patterns.md +192 -0
- package/skills/cloudflare/references/workers/README.md +108 -0
- package/skills/cloudflare/references/workers/api.md +195 -0
- package/skills/cloudflare/references/workers/configuration.md +185 -0
- package/skills/cloudflare/references/workers/frameworks.md +197 -0
- package/skills/cloudflare/references/workers/gotchas.md +137 -0
- package/skills/cloudflare/references/workers/patterns.md +198 -0
- package/skills/cloudflare/references/workers-ai/README.md +197 -0
- package/skills/cloudflare/references/workers-ai/api.md +112 -0
- package/skills/cloudflare/references/workers-ai/configuration.md +97 -0
- package/skills/cloudflare/references/workers-ai/gotchas.md +114 -0
- package/skills/cloudflare/references/workers-ai/patterns.md +120 -0
- package/skills/cloudflare/references/workers-for-platforms/README.md +89 -0
- package/skills/cloudflare/references/workers-for-platforms/api.md +196 -0
- package/skills/cloudflare/references/workers-for-platforms/configuration.md +167 -0
- package/skills/cloudflare/references/workers-for-platforms/gotchas.md +134 -0
- package/skills/cloudflare/references/workers-for-platforms/patterns.md +188 -0
- package/skills/cloudflare/references/workers-playground/README.md +127 -0
- package/skills/cloudflare/references/workers-playground/api.md +101 -0
- package/skills/cloudflare/references/workers-playground/configuration.md +163 -0
- package/skills/cloudflare/references/workers-playground/gotchas.md +88 -0
- package/skills/cloudflare/references/workers-playground/patterns.md +132 -0
- package/skills/cloudflare/references/workers-vpc/README.md +127 -0
- package/skills/cloudflare/references/workers-vpc/api.md +202 -0
- package/skills/cloudflare/references/workers-vpc/configuration.md +147 -0
- package/skills/cloudflare/references/workers-vpc/gotchas.md +167 -0
- package/skills/cloudflare/references/workers-vpc/patterns.md +209 -0
- package/skills/cloudflare/references/workflows/README.md +77 -0
- package/skills/cloudflare/references/workflows/api.md +218 -0
- package/skills/cloudflare/references/workflows/configuration.md +152 -0
- package/skills/cloudflare/references/workflows/gotchas.md +90 -0
- package/skills/cloudflare/references/workflows/patterns.md +175 -0
- package/skills/cloudflare/references/wrangler/README.md +135 -0
- package/skills/cloudflare/references/wrangler/api.md +188 -0
- package/skills/cloudflare/references/wrangler/configuration.md +197 -0
- package/skills/cloudflare/references/wrangler/gotchas.md +197 -0
- package/skills/cloudflare/references/wrangler/patterns.md +209 -0
- package/skills/cloudflare/references/zaraz/IMPLEMENTATION_SUMMARY.md +121 -0
- package/skills/cloudflare/references/zaraz/README.md +111 -0
- package/skills/cloudflare/references/zaraz/api.md +112 -0
- package/skills/cloudflare/references/zaraz/configuration.md +90 -0
- package/skills/cloudflare/references/zaraz/gotchas.md +81 -0
- package/skills/cloudflare/references/zaraz/patterns.md +74 -0
- package/skills/cloudflare-email-service/SKILL.md +103 -0
- package/skills/cloudflare-email-service/references/cli-and-mcp.md +125 -0
- package/skills/cloudflare-email-service/references/deliverability.md +285 -0
- package/skills/cloudflare-email-service/references/rest-api.md +184 -0
- package/skills/cloudflare-email-service/references/routing.md +199 -0
- package/skills/cloudflare-email-service/references/sending.md +252 -0
- package/skills/cloudflare-one/SKILL.md +176 -0
- package/skills/cloudflare-one-migrations/SKILL.md +110 -0
- package/skills/durable-objects/SKILL.md +186 -0
- package/skills/durable-objects/references/rules.md +295 -0
- package/skills/durable-objects/references/testing.md +264 -0
- package/skills/durable-objects/references/workers.md +346 -0
- package/skills/sandbox-migrate-to-next/SKILL.md +185 -0
- package/skills/sandbox-next/SKILL.md +91 -0
- package/skills/sandbox-next/references/api-quick-ref.md +94 -0
- package/skills/sandbox-next/references/examples.md +15 -0
- package/skills/sandbox-stable/SKILL.md +110 -0
- package/skills/turnstile-spin/README.md +51 -0
- package/skills/turnstile-spin/SKILL.md +330 -0
- package/skills/turnstile-spin/references/astro.md +199 -0
- package/skills/turnstile-spin/references/hugo.md +114 -0
- package/skills/turnstile-spin/references/nextjs-app.md +261 -0
- package/skills/turnstile-spin/references/nextjs-pages.md +82 -0
- package/skills/turnstile-spin/references/sveltekit.md +191 -0
- package/skills/turnstile-spin/references/vanilla-html.md +157 -0
- package/skills/turnstile-spin/scripts/auth-probe.sh +285 -0
- package/skills/turnstile-spin/scripts/persist-skill.sh +114 -0
- package/skills/turnstile-spin/scripts/validate.sh +137 -0
- package/skills/turnstile-spin/scripts/widget-create.sh +121 -0
- package/skills/turnstile-spin/tests/validation.md +62 -0
- package/skills/workers-best-practices/SKILL.md +127 -0
- package/skills/workers-best-practices/references/review.md +174 -0
- package/skills/workers-best-practices/references/rules.md +467 -0
- package/skills/wrangler/SKILL.md +922 -0
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
|
|
11
|
+
// Manual iteration
|
|
12
|
+
const iter = cursor[Symbol.iterator]();
|
|
13
|
+
const first = iter.next(); // { value: {...}, done: false }
|
|
14
|
+
|
|
15
|
+
cursor.columnNames; // ["id", "name", "email"]
|
|
16
|
+
cursor.rowsRead; cursor.rowsWritten; // Billing
|
|
17
|
+
|
|
18
|
+
type User = { id: number; name: string; email: string };
|
|
19
|
+
const user = this.sql.exec<User>('...', userId).one();
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Sync KV API (SQLite only)
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
this.ctx.storage.kv.get("counter"); // undefined if missing
|
|
26
|
+
this.ctx.storage.kv.put("counter", 42);
|
|
27
|
+
this.ctx.storage.kv.put("user", { name: "Alice", age: 30 });
|
|
28
|
+
this.ctx.storage.kv.delete("counter"); // true if existed
|
|
29
|
+
|
|
30
|
+
for (let [key, value] of this.ctx.storage.kv.list()) {}
|
|
31
|
+
|
|
32
|
+
// List options: start, prefix, reverse, limit
|
|
33
|
+
this.ctx.storage.kv.list({ start: "user:", prefix: "user:", reverse: true, limit: 100 });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Async KV API (Both backends)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
await this.ctx.storage.get("key"); // Single
|
|
40
|
+
await this.ctx.storage.get(["key1", "key2"]); // Multiple (max 128)
|
|
41
|
+
await this.ctx.storage.put("key", value); // Single
|
|
42
|
+
await this.ctx.storage.put({ "key1": "v1", "key2": { nested: true } }); // Multiple (max 128)
|
|
43
|
+
await this.ctx.storage.delete("key");
|
|
44
|
+
await this.ctx.storage.delete(["key1", "key2"]);
|
|
45
|
+
await this.ctx.storage.list({ prefix: "user:", limit: 100 });
|
|
46
|
+
|
|
47
|
+
// Options: allowConcurrency, noCache, allowUnconfirmed
|
|
48
|
+
await this.ctx.storage.get("key", { allowConcurrency: true, noCache: true });
|
|
49
|
+
await this.ctx.storage.put("key", value, { allowUnconfirmed: true, noCache: true });
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Storage Options
|
|
53
|
+
|
|
54
|
+
| Option | Methods | Effect | Use Case |
|
|
55
|
+
|--------|---------|--------|----------|
|
|
56
|
+
| `allowConcurrency` | get, list | Skip input gate; allow concurrent requests during read | Read-heavy metrics that don't need strict consistency |
|
|
57
|
+
| `noCache` | get, put, list | Skip in-memory cache; always read from disk | Rarely-accessed data or testing storage directly |
|
|
58
|
+
| `allowUnconfirmed` | put, delete | Return before write confirms (still protected by output gate) | Non-critical writes where latency matters more than confirmation |
|
|
59
|
+
|
|
60
|
+
## Transactions
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Sync (SQL/sync KV only)
|
|
64
|
+
this.ctx.storage.transactionSync(() => {
|
|
65
|
+
this.sql.exec('UPDATE accounts SET balance = balance - ? WHERE id = ?', 100, 1);
|
|
66
|
+
this.sql.exec('UPDATE accounts SET balance = balance + ? WHERE id = ?', 100, 2);
|
|
67
|
+
return "result";
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Async
|
|
71
|
+
await this.ctx.storage.transaction(async () => {
|
|
72
|
+
const value = await this.ctx.storage.get("counter");
|
|
73
|
+
await this.ctx.storage.put("counter", value + 1);
|
|
74
|
+
if (value > 100) this.ctx.storage.rollback(); // Explicit rollback
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Point-in-Time Recovery
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
await this.ctx.storage.getCurrentBookmark();
|
|
82
|
+
await this.ctx.storage.getBookmarkForTime(Date.now() - 2 * 24 * 60 * 60 * 1000);
|
|
83
|
+
await this.ctx.storage.onNextSessionRestoreBookmark(bookmark);
|
|
84
|
+
this.ctx.abort(); // Restart to apply; bookmarks lexically comparable (earlier < later)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Alarms
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
await this.ctx.storage.setAlarm(Date.now() + 60000); // Timestamp or Date
|
|
91
|
+
await this.ctx.storage.getAlarm();
|
|
92
|
+
await this.ctx.storage.deleteAlarm();
|
|
93
|
+
|
|
94
|
+
async alarm() { await this.doScheduledWork(); }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Misc
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
await this.ctx.storage.deleteAll(); // Atomic for SQLite; alarm NOT included
|
|
101
|
+
this.ctx.storage.sql.databaseSize; // Bytes
|
|
102
|
+
```
|
|
@@ -0,0 +1,112 @@
|
|
|
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
|
+
**Migration lifecycle:** Migrations run once per deployment. Existing DO instances get new storage backend on next invocation. Renaming/removing classes requires `renamed_classes` or `deleted_classes` entries.
|
|
18
|
+
|
|
19
|
+
## KV-backed (Legacy)
|
|
20
|
+
|
|
21
|
+
**wrangler.jsonc:**
|
|
22
|
+
```jsonc
|
|
23
|
+
{
|
|
24
|
+
"migrations": [
|
|
25
|
+
{
|
|
26
|
+
"tag": "v1",
|
|
27
|
+
"new_classes": ["OldCounter"]
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## TypeScript Setup
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
export class MyDurableObject extends DurableObject {
|
|
37
|
+
sql: SqlStorage;
|
|
38
|
+
|
|
39
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
40
|
+
super(ctx, env);
|
|
41
|
+
this.sql = ctx.storage.sql;
|
|
42
|
+
|
|
43
|
+
// Initialize schema
|
|
44
|
+
this.sql.exec(`
|
|
45
|
+
CREATE TABLE IF NOT EXISTS users(
|
|
46
|
+
id INTEGER PRIMARY KEY,
|
|
47
|
+
name TEXT NOT NULL,
|
|
48
|
+
email TEXT UNIQUE
|
|
49
|
+
);
|
|
50
|
+
`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Binding
|
|
55
|
+
interface Env {
|
|
56
|
+
MY_DO: DurableObjectNamespace;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default {
|
|
60
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
61
|
+
const id = env.MY_DO.idFromName('singleton');
|
|
62
|
+
const stub = env.MY_DO.get(id);
|
|
63
|
+
|
|
64
|
+
// Modern RPC: call methods directly (recommended)
|
|
65
|
+
const result = await stub.someMethod();
|
|
66
|
+
return Response.json(result);
|
|
67
|
+
|
|
68
|
+
// Legacy: forward request (still works)
|
|
69
|
+
// return stub.fetch(request);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## CPU Limits
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
{
|
|
78
|
+
"limits": {
|
|
79
|
+
"cpu_ms": 300000 // 5 minutes (default 30s)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Location Control
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Jurisdiction (GDPR/FedRAMP)
|
|
88
|
+
const euNamespace = env.MY_DO.jurisdiction("eu");
|
|
89
|
+
const id = euNamespace.newUniqueId();
|
|
90
|
+
const stub = euNamespace.get(id);
|
|
91
|
+
|
|
92
|
+
// Location hint (best effort)
|
|
93
|
+
const stub = env.MY_DO.get(id, { locationHint: "enam" });
|
|
94
|
+
// Hints: wnam, enam, sam, weur, eeur, apac, oc, afr, me
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Initialization
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
export class Counter extends DurableObject {
|
|
101
|
+
value: number;
|
|
102
|
+
|
|
103
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
104
|
+
super(ctx, env);
|
|
105
|
+
|
|
106
|
+
// Block concurrent requests during init
|
|
107
|
+
ctx.blockConcurrencyWhile(async () => {
|
|
108
|
+
this.value = (await ctx.storage.get("value")) || 0;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# DO Storage Gotchas & Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Concurrency Model (CRITICAL)
|
|
4
|
+
|
|
5
|
+
Durable Objects use **input/output gates** to prevent race conditions:
|
|
6
|
+
|
|
7
|
+
### Input Gates
|
|
8
|
+
Block new requests during storage reads from CURRENT request:
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
// SAFE: Input gate active during await
|
|
12
|
+
async increment() {
|
|
13
|
+
const val = await this.ctx.storage.get("counter"); // Input gate blocks other requests
|
|
14
|
+
await this.ctx.storage.put("counter", val + 1);
|
|
15
|
+
return val;
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Output Gates
|
|
20
|
+
Hold response until ALL writes from current request confirm:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// SAFE: Output gate waits for put() to confirm before returning response
|
|
24
|
+
async increment() {
|
|
25
|
+
const val = await this.ctx.storage.get("counter");
|
|
26
|
+
this.ctx.storage.put("counter", val + 1); // No await
|
|
27
|
+
return new Response(String(val)); // Response delayed until write confirms
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Write Coalescing
|
|
32
|
+
Multiple writes to same key = atomic (last write wins):
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// SAFE: All three writes coalesce atomically
|
|
36
|
+
this.ctx.storage.put("key", 1);
|
|
37
|
+
this.ctx.storage.put("key", 2);
|
|
38
|
+
this.ctx.storage.put("key", 3); // Final value: 3
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Breaking Gates (DANGER)
|
|
42
|
+
|
|
43
|
+
**fetch() breaks input/output gates** → allows request interleaving:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// UNSAFE: fetch() allows another request to interleave
|
|
47
|
+
async unsafe() {
|
|
48
|
+
const val = await this.ctx.storage.get("counter");
|
|
49
|
+
await fetch("https://api.example.com"); // Gate broken!
|
|
50
|
+
await this.ctx.storage.put("counter", val + 1); // Race condition possible
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Solution:** Use `blockConcurrencyWhile()` or `transaction()`:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// SAFE: Block concurrent requests explicitly
|
|
58
|
+
async safe() {
|
|
59
|
+
return await this.ctx.blockConcurrencyWhile(async () => {
|
|
60
|
+
const val = await this.ctx.storage.get("counter");
|
|
61
|
+
await fetch("https://api.example.com");
|
|
62
|
+
await this.ctx.storage.put("counter", val + 1);
|
|
63
|
+
return val;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### allowConcurrency Option
|
|
69
|
+
|
|
70
|
+
Opt out of input gate for reads that don't need protection:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Allow concurrent reads (no consistency guarantee)
|
|
74
|
+
const val = await this.ctx.storage.get("metrics", { allowConcurrency: true });
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Common Errors
|
|
78
|
+
|
|
79
|
+
### "Race Condition in Concurrent Calls"
|
|
80
|
+
|
|
81
|
+
**Cause:** Multiple concurrent storage operations initiated from same event (e.g., `Promise.all()`) are not protected by input gate
|
|
82
|
+
**Solution:** Avoid concurrent storage operations within single event; input gate only serializes requests from different events, not operations within same event
|
|
83
|
+
|
|
84
|
+
### "Direct SQL Transaction Statements"
|
|
85
|
+
|
|
86
|
+
**Cause:** Using `BEGIN TRANSACTION` directly instead of transaction methods
|
|
87
|
+
**Solution:** Use `this.ctx.storage.transactionSync()` for sync operations or `this.ctx.storage.transaction()` for async operations
|
|
88
|
+
|
|
89
|
+
### "Async in transactionSync"
|
|
90
|
+
|
|
91
|
+
**Cause:** Using async operations inside `transactionSync()` callback
|
|
92
|
+
**Solution:** Use async `transaction()` method instead of `transactionSync()` when async operations needed
|
|
93
|
+
|
|
94
|
+
### "TypeScript Type Mismatch at Runtime"
|
|
95
|
+
|
|
96
|
+
**Cause:** Query doesn't return all fields specified in TypeScript type
|
|
97
|
+
**Solution:** Ensure SQL query selects all columns that match the TypeScript type definition
|
|
98
|
+
|
|
99
|
+
### "Silent Data Corruption with Large IDs"
|
|
100
|
+
|
|
101
|
+
**Cause:** JavaScript numbers have 53-bit precision; SQLite INTEGER is 64-bit
|
|
102
|
+
**Symptom:** IDs > 9007199254740991 (Number.MAX_SAFE_INTEGER) silently truncate/corrupt
|
|
103
|
+
**Solution:** Store large IDs as TEXT:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
// BAD: Snowflake/Twitter IDs will corrupt
|
|
107
|
+
this.sql.exec("CREATE TABLE events(id INTEGER PRIMARY KEY)");
|
|
108
|
+
this.sql.exec("INSERT INTO events VALUES (?)", 1234567890123456789n); // Corrupts!
|
|
109
|
+
|
|
110
|
+
// GOOD: Store as TEXT
|
|
111
|
+
this.sql.exec("CREATE TABLE events(id TEXT PRIMARY KEY)");
|
|
112
|
+
this.sql.exec("INSERT INTO events VALUES (?)", "1234567890123456789");
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### "Alarm Not Deleted with deleteAll()"
|
|
116
|
+
|
|
117
|
+
**Cause:** `deleteAll()` doesn't delete alarms automatically
|
|
118
|
+
**Solution:** Call `deleteAlarm()` explicitly before `deleteAll()` to remove alarm
|
|
119
|
+
|
|
120
|
+
### "Slow Performance"
|
|
121
|
+
|
|
122
|
+
**Cause:** Using async KV API instead of sync API
|
|
123
|
+
**Solution:** Use sync KV API (`ctx.storage.kv`) for better performance with simple key-value operations
|
|
124
|
+
|
|
125
|
+
### "High Billing from Storage Operations"
|
|
126
|
+
|
|
127
|
+
**Cause:** Excessive `rowsRead`/`rowsWritten` or unused objects not cleaned up
|
|
128
|
+
**Solution:** Monitor `rowsRead`/`rowsWritten` metrics and ensure unused objects call `deleteAll()`
|
|
129
|
+
|
|
130
|
+
### "Durable Object Overloaded"
|
|
131
|
+
|
|
132
|
+
**Cause:** Single DO exceeding ~1K req/sec soft limit
|
|
133
|
+
**Solution:** Shard across multiple DOs with random IDs or other distribution strategy
|
|
134
|
+
|
|
135
|
+
## Limits
|
|
136
|
+
|
|
137
|
+
| Limit | Value | Notes |
|
|
138
|
+
|-------|-------|-------|
|
|
139
|
+
| Max columns per table | 100 | SQL limitation |
|
|
140
|
+
| Max string/BLOB per row | 2 MB | SQL limitation |
|
|
141
|
+
| Max row size | 2 MB | SQL limitation |
|
|
142
|
+
| Max SQL statement size | 100 KB | SQL limitation |
|
|
143
|
+
| Max SQL parameters | 100 | SQL limitation |
|
|
144
|
+
| Max LIKE/GLOB pattern | 50 B | SQL limitation |
|
|
145
|
+
| SQLite storage per object | 10 GB | SQLite-backed storage |
|
|
146
|
+
| SQLite key+value size | 2 MB | SQLite-backed storage |
|
|
147
|
+
| KV storage per object | Unlimited | KV-style storage |
|
|
148
|
+
| KV key size | 2 KiB | KV-style storage |
|
|
149
|
+
| KV value size | 128 KiB | KV-style storage |
|
|
150
|
+
| Request throughput | ~1K req/sec | Soft limit per DO |
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# DO Storage Patterns & Best Practices
|
|
2
|
+
|
|
3
|
+
## Schema Migration
|
|
4
|
+
|
|
5
|
+
**Note:** `PRAGMA user_version` is **not supported** in Durable Objects SQLite storage. Use a `_sql_schema_migrations` table instead:
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
export class MyDurableObject extends DurableObject {
|
|
9
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
10
|
+
super(ctx, env);
|
|
11
|
+
this.sql = ctx.storage.sql;
|
|
12
|
+
|
|
13
|
+
this.sql.exec(`
|
|
14
|
+
CREATE TABLE IF NOT EXISTS _sql_schema_migrations (
|
|
15
|
+
id INTEGER PRIMARY KEY,
|
|
16
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
17
|
+
)
|
|
18
|
+
`);
|
|
19
|
+
|
|
20
|
+
const ver = this.sql
|
|
21
|
+
.exec<{ version: number }>("SELECT COALESCE(MAX(id), 0) as version FROM _sql_schema_migrations")
|
|
22
|
+
.one().version;
|
|
23
|
+
|
|
24
|
+
if (ver < 1) {
|
|
25
|
+
this.sql.exec(`CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT)`);
|
|
26
|
+
this.sql.exec("INSERT INTO _sql_schema_migrations (id) VALUES (1)");
|
|
27
|
+
}
|
|
28
|
+
if (ver < 2) {
|
|
29
|
+
this.sql.exec(`ALTER TABLE users ADD COLUMN email TEXT`);
|
|
30
|
+
this.sql.exec("INSERT INTO _sql_schema_migrations (id) VALUES (2)");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For production apps, consider [`durable-utils`](https://github.com/lambrospetrou/durable-utils#sqlite-schema-migrations) — provides a `SQLSchemaMigrations` class that tracks executed migrations both in memory and in storage. Also see [`@cloudflare/actors` storage utilities](https://github.com/cloudflare/actors/blob/main/packages/storage/src/sql-schema-migrations.ts) — a reference implementation of the same pattern used by the Cloudflare Actors framework.
|
|
37
|
+
|
|
38
|
+
## In-Memory Caching
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
export class UserCache extends DurableObject {
|
|
42
|
+
cache = new Map<string, User>();
|
|
43
|
+
async getUser(id: string): Promise<User | undefined> {
|
|
44
|
+
if (this.cache.has(id)) {
|
|
45
|
+
const cached = this.cache.get(id);
|
|
46
|
+
if (cached) return cached;
|
|
47
|
+
}
|
|
48
|
+
const user = await this.ctx.storage.get<User>(`user:${id}`);
|
|
49
|
+
if (user) this.cache.set(id, user);
|
|
50
|
+
return user;
|
|
51
|
+
}
|
|
52
|
+
async updateUser(id: string, data: Partial<User>) {
|
|
53
|
+
const updated = { ...await this.getUser(id), ...data };
|
|
54
|
+
this.cache.set(id, updated);
|
|
55
|
+
await this.ctx.storage.put(`user:${id}`, updated);
|
|
56
|
+
return updated;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Rate Limiting
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
export class RateLimiter extends DurableObject {
|
|
65
|
+
async checkLimit(key: string, limit: number, window: number): Promise<boolean> {
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
this.sql.exec('DELETE FROM requests WHERE key = ? AND timestamp < ?', key, now - window);
|
|
68
|
+
const count = this.sql.exec('SELECT COUNT(*) as count FROM requests WHERE key = ?', key).one().count;
|
|
69
|
+
if (count >= limit) return false;
|
|
70
|
+
this.sql.exec('INSERT INTO requests (key, timestamp) VALUES (?, ?)', key, now);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Batch Processing with Alarms
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
export class BatchProcessor extends DurableObject {
|
|
80
|
+
pending: string[] = [];
|
|
81
|
+
async addItem(item: string) {
|
|
82
|
+
this.pending.push(item);
|
|
83
|
+
if (!await this.ctx.storage.getAlarm()) await this.ctx.storage.setAlarm(Date.now() + 5000);
|
|
84
|
+
}
|
|
85
|
+
async alarm() {
|
|
86
|
+
const items = [...this.pending];
|
|
87
|
+
this.pending = [];
|
|
88
|
+
this.sql.exec(`INSERT INTO processed_items (item, timestamp) VALUES ${items.map(() => "(?, ?)").join(", ")}`, ...items.flatMap(item => [item, Date.now()]));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Initialization Pattern
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
export class Counter extends DurableObject {
|
|
97
|
+
value: number;
|
|
98
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
99
|
+
super(ctx, env);
|
|
100
|
+
ctx.blockConcurrencyWhile(async () => { this.value = (await ctx.storage.get("value")) || 0; });
|
|
101
|
+
}
|
|
102
|
+
async increment() {
|
|
103
|
+
this.value++;
|
|
104
|
+
this.ctx.storage.put("value", this.value); // Don't await (output gate protects)
|
|
105
|
+
return this.value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Safe Counter / Optimized Write
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Input gate blocks other requests
|
|
114
|
+
async getUniqueNumber(): Promise<number> {
|
|
115
|
+
let val = await this.ctx.storage.get("counter");
|
|
116
|
+
await this.ctx.storage.put("counter", val + 1);
|
|
117
|
+
return val;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// No await on write - output gate delays response until write confirms
|
|
121
|
+
async increment(): Promise<Response> {
|
|
122
|
+
let val = await this.ctx.storage.get("counter");
|
|
123
|
+
this.ctx.storage.put("counter", val + 1);
|
|
124
|
+
return new Response(String(val));
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Parent-Child Coordination
|
|
129
|
+
|
|
130
|
+
Hierarchical DO pattern where parent manages child DOs:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// Parent DO coordinates children
|
|
134
|
+
export class Workspace extends DurableObject {
|
|
135
|
+
async createDocument(name: string): Promise<string> {
|
|
136
|
+
const docId = crypto.randomUUID();
|
|
137
|
+
const childId = this.env.DOCUMENT.idFromName(`${this.ctx.id.toString()}:${docId}`);
|
|
138
|
+
const childStub = this.env.DOCUMENT.get(childId);
|
|
139
|
+
await childStub.initialize(name);
|
|
140
|
+
|
|
141
|
+
// Track child in parent storage
|
|
142
|
+
this.sql.exec('INSERT INTO documents (id, name, created) VALUES (?, ?, ?)',
|
|
143
|
+
docId, name, Date.now());
|
|
144
|
+
return docId;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async listDocuments(): Promise<string[]> {
|
|
148
|
+
return this.sql.exec('SELECT id FROM documents').toArray().map(r => r.id);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Child DO
|
|
153
|
+
export class Document extends DurableObject {
|
|
154
|
+
async initialize(name: string) {
|
|
155
|
+
this.sql.exec('CREATE TABLE IF NOT EXISTS content(key TEXT PRIMARY KEY, value TEXT)');
|
|
156
|
+
this.sql.exec('INSERT INTO content VALUES (?, ?)', 'name', name);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Write Coalescing Pattern
|
|
162
|
+
|
|
163
|
+
Multiple writes to same key coalesce atomically (last write wins):
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
async updateMetrics(userId: string, actions: Action[]) {
|
|
167
|
+
// All writes coalesce - no await needed
|
|
168
|
+
for (const action of actions) {
|
|
169
|
+
this.ctx.storage.put(`user:${userId}:lastAction`, action.type);
|
|
170
|
+
this.ctx.storage.put(`user:${userId}:count`,
|
|
171
|
+
await this.ctx.storage.get(`user:${userId}:count`) + 1);
|
|
172
|
+
}
|
|
173
|
+
// Output gate ensures all writes confirm before response
|
|
174
|
+
return new Response("OK");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Atomic batch with SQL
|
|
178
|
+
async batchUpdate(items: Item[]) {
|
|
179
|
+
this.sql.exec('BEGIN');
|
|
180
|
+
for (const item of items) {
|
|
181
|
+
this.sql.exec('INSERT OR REPLACE INTO items VALUES (?, ?)', item.id, item.value);
|
|
182
|
+
}
|
|
183
|
+
this.sql.exec('COMMIT');
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Cleanup
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
async cleanup() {
|
|
191
|
+
await this.ctx.storage.deleteAlarm(); // Separate from deleteAll
|
|
192
|
+
await this.ctx.storage.deleteAll();
|
|
193
|
+
}
|
|
194
|
+
```
|