7.7 KiB
Cloudflare Workers
STOP. Your knowledge of Cloudflare Workers APIs and limits may be outdated. Always retrieve current documentation before any Workers, KV, R2, D1, Durable Objects, Queues, Vectorize, AI, or Agents SDK task.
Docs
- https://developers.cloudflare.com/workers/
- MCP:
https://docs.mcp.cloudflare.com/mcp
For all limits and quotas, retrieve from the product's /platform/limits/ page. e.g. /workers/platform/limits
Product Docs
Retrieve API references and limits from:
/kv/ · /r2/ · /d1/ · /durable-objects/ · /queues/ · /vectorize/ · /workers-ai/ · /agents/
Errors
- Error 1102 (CPU/Memory exceeded): Retrieve limits from
/workers/platform/limits/ - All errors: https://developers.cloudflare.com/workers/observability/errors/
Project: tangfamily
A Cloudflare Workers full-stack family tree website. The single Worker at src/index.ts serves all API routes; static HTML pages in public/ are served via Cloudflare's asset pipeline (env.ASSETS). Data is stored in a KV namespace (FAMILY_DATA). Deployed at https://tangfamily.shumengya666.workers.dev.
Commands
| Command | Purpose |
|---|---|
npm run dev |
Start local dev server (http://127.0.0.1:8787) |
npm run deploy |
Deploy to Cloudflare |
npm test |
Run all tests (vitest watch mode) |
npm run cf-typegen |
Regenerate worker-configuration.d.ts from wrangler.jsonc |
Run a single test file:
npx vitest run test/index.spec.ts
Run a single test by name:
npx vitest run -t "test name here"
Always run npm run cf-typegen after changing any bindings in wrangler.jsonc.
There is no lint script. Format with Prettier manually if needed:
npx prettier --write "src/**/*.ts"
Project Structure
src/index.ts # Single-file Worker: all API handlers + routing + CORS
public/index.html # Visitor login page
public/tree.html # Family tree viewer (authenticated visitors)
public/admin-login.html # Admin login
public/admin.html # Admin CRUD panel
test/index.spec.ts # Vitest integration tests (runs inside Workers runtime)
test/tsconfig.json # Extends root tsconfig; adds vitest-pool-workers types
test/env.d.ts # Merges Env into cloudflare:test module
vitest.config.mts # Vitest config — uses defineWorkersConfig + wrangler.jsonc
wrangler.jsonc # Worker config: entry, KV binding, assets, compat flags
worker-configuration.d.ts # Auto-generated by cf-typegen — do not edit manually
Architecture
- All API logic lives in
src/index.ts; there are no other Worker source files. public/*.htmlpages are pure HTML with inline CSS and inline<script>— no bundler, no frameworks.- KV stores two kinds of keys:
members→ JSON-serialisedFamilyMember[]session:{uuid}→ JSON{ isAdmin: boolean, createdAt: number }, TTL 24h
- Auth is token-based: login returns a UUID token stored in KV; the client stores it in
localStorage. - CORS headers are applied in the main
fetchdispatcher, not inside individual handlers. - Static assets are served by
env.ASSETS.fetch(request)as the default fallback.
API Routes
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/login |
none | Returns session token |
GET |
/api/members |
visitor+ | List all members |
POST |
/api/members |
admin | Add or update a member |
POST |
/api/members/delete |
admin | Delete a member by id |
Data Shape
interface FamilyMember {
id: string;
name: string;
birthYear: number;
gender: '男' | '女';
generation?: string;
fatherId?: string;
motherId?: string;
}
Node.js Compatibility
https://developers.cloudflare.com/workers/runtime-apis/nodejs/
The nodejs_compat flag is enabled. The global_fetch_strictly_public flag is also active — fetch() cannot reach private/internal addresses.
TypeScript
strict: true— all strict checks are on; do not disable any of them.target/lib: es2024— use modern JS features freely.moduleResolution: "Bundler"— do not use Node-stylerequire()or.jsextensions in imports.noEmit: true— Wrangler compiles;tscis for type-checking only.isolatedModules: true— every file must be independently transpilable; avoid type-only re-exports without thetypekeyword.- Prefer
interfaceovertypefor object shapes. - Use
satisfiesinstead ofasfor the default Worker export:} satisfies ExportedHandler<Env>. - Cast JSON parse results with
as:await request.json() as MyType. - Use literal union types for constrained values:
gender: '男' | '女'.
Code Style
Formatting (Prettier + EditorConfig)
- Indentation: tabs (not spaces), everywhere except YAML.
- Line endings: LF.
- Quotes: single quotes in TypeScript/JS.
- Semicolons: always.
- Print width: 140 characters.
- Trim trailing whitespace; always end files with a newline.
Naming Conventions
- Functions:
camelCase; request handlers prefixed withhandle(handleLogin,handleGetMembers). - Interfaces/Types:
PascalCase(FamilyMember,Env). - Constants:
SCREAMING_SNAKE_CASE(VISITOR_PASSWORD,ADMIN_PASSWORD). - Variables:
camelCase(membersJson,sessionData,corsHeaders). - KV keys: lowercase with colon-separated namespaces (
session:{uuid},members). - HTML element IDs:
camelCase(membersList,memberBirthYear). - CSS classes:
kebab-case(member-card,btn-danger).
Imports
- Worker source (
src/) has no imports — use Workers runtime globals only (crypto,KVNamespace,Request,Response,Headers,URL,ExecutionContext,ExportedHandler). - In tests, import from
cloudflare:testandvitestfirst, then local modules. - No path aliases. Use relative paths (
../src).
Error Handling
- All async handlers use
try/catch. - The
catchblock returns a structured JSON error response with an appropriate HTTP status code. - Do not log or inspect the caught
errorvariable in Worker code — translate to a user-facing message in Chinese. - Return
401for unauthenticated,403for unauthorised (missing admin),400for bad input,404for unknown routes,405for wrong method.
} catch (error) {
return new Response(JSON.stringify({ success: false, error: '操作失败' }), {
status: 400,
headers: { 'Content-Type': 'application/json' },
});
}
Response Pattern
- Construct JSON responses with
new Response(JSON.stringify({...}), { headers: { 'Content-Type': 'application/json' } }). - Do not add CORS headers inside handlers — they are merged in the main dispatcher.
- Return
nullbody with{ headers: corsHeaders }forOPTIONSpreflight.
Async/Await
- All handlers are
async function, returningPromise<Response>. - Use
async/awaitexclusively — no.then()/.catch()chains. - KV reads are awaited sequentially; use
Promise.allonly when operations are truly independent. - Call
await verifyToken(...)as the first gate in every protected handler.
Testing
- Tests run inside the real Cloudflare Workers runtime via
@cloudflare/vitest-pool-workers— not Node.js. vitest.config.mtsusesdefineWorkersConfigand points atwrangler.jsoncfor bindings.- The
test/directory has its owntsconfig.json(extends root, adds@cloudflare/vitest-pool-workerstypes). - Use
envfromcloudflare:testto access bindings directly; useSELF.fetch()for integration-style HTTP requests. - Type-cast
.json()results:await res.json() as { token: string }. - Do not add test-only logic to
src/index.ts. - After adding new bindings to
wrangler.jsonc, runnpm run cf-typegenbefore writing tests.