@kentcdodds/cloudflare
README.md
131 lines · 5.2 KB · Markdown@kentcdodds/cloudflare
Intent
Account-aware Cloudflare API v4, GraphQL analytics, Rulesets/WAF, Log Explorer, and developer-doc helpers for Kody workflows — centralizes token selection so agents can target the right Cloudflare account without hardcoding a single secret. Also provides a safe token-verify helper so account-scoped tokens are not misread as invalid.
When To Use
- Call Cloudflare API v4 for zones, Workers, D1, R2, KV, or related resources
- Verify whether a saved Cloudflare token secret is alive (user-scoped vs account-scoped)
- Summarize zone HTTP traffic by status, path, or user agent during outage forensics
- Search Workers traces, HTTP requests, or Access events via Log Explorer SQL
- Preview or apply WAF custom rules that block bogus crawler routes before origin
- Fetch allowlisted Cloudflare developer documentation while building integrations
- Choose between
default,kody, orpagesAPI tokens for an operation
Required setup
Three saved Cloudflare API token secrets (user scope), one per account alias:
cloudflareApiToken—defaultaccount (primary token for routine API work).cloudflareApiTokenKodyAccount—kodyaccount (Kody Cloudflare account resources).cloudflarePagesApiToken—pagesaccount (dedicated Cloudflare Pages token).
Approve api.cloudflare.com for each secret you use. Grant firewall/ruleset edit permission only if you use rulesets with apply: true.
Account guide
| Account | Default | Secret | Use when |
|---|---|---|---|
default | Yes | cloudflareApiToken | Routine API, analytics, logs, and WAF work on accounts the primary token covers. |
kody | No | cloudflareApiTokenKodyAccount | Kody Cloudflare account resources (for example Kody production D1) when the default token is unauthorized. |
pages | No | cloudflarePagesApiToken | Cloudflare Pages operations that need the dedicated Pages token. |
Authenticated exports accept optional account (default 'default'). For a token outside this table, pass apiTokenSecret with the Kody secret name (never a raw token value). Do not pass both account and apiTokenSecret.
Verifying API tokens (read this)
Cloudflare has two verify endpoints. Using the wrong one produces a misleading 401 Invalid API Token for a perfectly valid token.
| Token kind | Where it was created | Verify with |
|---|---|---|
| User API token | My Profile → API Tokens | GET /client/v4/user/tokens/verify |
| Account API token | Manage Account → API Tokens | GET /client/v4/accounts/{account_id}/tokens/verify |
Agents: never conclude a secret is broken from /user/tokens/verify alone. Prefer this package’s verify export:
import verifyApiToken from 'kody:@kentcdodds/cloudflare/verify'
export default async function main() {
return await verifyApiToken({ account: 'kody' })
// => { ok: true, kind: 'account', status: 'active', ... }
}account: 'kody' uses the known Kody account id. For other account-scoped tokens, pass accountId.
After verify succeeds, interpret resource probes as:
| HTTP status | Meaning |
|---|---|
401 | Token rejected (or wrong verify endpoint — see above) |
403 | Token valid, lacks that permission / account access |
400 / 404 on a mutating call against a bad/missing target | Token is authorized for that operation |
Exports
kody:@kentcdodds/cloudflare/overview— package discovery metadatakody:@kentcdodds/cloudflare/accounts— token aliases and selection guidancekody:@kentcdodds/cloudflare/verify— safe user/account token verificationkody:@kentcdodds/cloudflare/api-v4— REST calls under/client/v4/(mutating)kody:@kentcdodds/cloudflare/analytics— GraphQL zone traffic summaries (read-only)kody:@kentcdodds/cloudflare/docs— fetch developer docs pages (read-only)kody:@kentcdodds/cloudflare/observability-logs— Log Explorer SQL search (read-only)kody:@kentcdodds/cloudflare/rulesets— WAF custom rule preview/apply (mutating; defaults to dry-run)
Examples
D1 query on the Kody Cloudflare account:
import cloudflareApiV4 from 'kody:@kentcdodds/cloudflare/api-v4'
export default async function main() {
return await cloudflareApiV4({
account: 'kody',
method: 'POST',
path: '/client/v4/accounts/ACCOUNT_ID/d1/database/DB_ID/query',
body: { sql: 'SELECT 1 AS ok' },
})
}Verify the Kody account token (correct endpoint):
import verifyApiToken from 'kody:@kentcdodds/cloudflare/verify'
export default async function main() {
return await verifyApiToken({ account: 'kody' })
}Traffic summary for a zone:
import analytics from 'kody:@kentcdodds/cloudflare/analytics'
export default async function main() {
return await analytics({ zoneName: 'example.com', last: '1h' })
}Search recent Worker trace events:
import searchLogs from 'kody:@kentcdodds/cloudflare/observability-logs'
export default async function main() {
return await searchLogs({
accountId: 'your-account-id',
scriptName: 'my-worker',
outcome: 'exception',
last: '30m',
limit: 25,
})
}Rulesets default to dry-run. Pass apply: true only after reviewing the returned entrypoint body.