181 lines
7.7 KiB
Markdown
181 lines
7.7 KiB
Markdown
# 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:**
|
|
```bash
|
|
npx vitest run test/index.spec.ts
|
|
```
|
|
|
|
**Run a single test by name:**
|
|
```bash
|
|
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:
|
|
```bash
|
|
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/*.html` pages are pure HTML with inline CSS and inline `<script>` — no bundler, no frameworks.
|
|
- KV stores two kinds of keys:
|
|
- `members` → JSON-serialised `FamilyMember[]`
|
|
- `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 `fetch` dispatcher, 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
|
|
|
|
```typescript
|
|
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-style `require()` or `.js` extensions in imports.
|
|
- **`noEmit: true`** — Wrangler compiles; `tsc` is for type-checking only.
|
|
- **`isolatedModules: true`** — every file must be independently transpilable; avoid type-only re-exports without the `type` keyword.
|
|
- Prefer `interface` over `type` for object shapes.
|
|
- Use `satisfies` instead of `as` for 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 with `handle` (`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:test` and `vitest` first, then local modules.
|
|
- No path aliases. Use relative paths (`../src`).
|
|
|
|
### Error Handling
|
|
- All async handlers use `try/catch`.
|
|
- The `catch` block returns a structured JSON error response with an appropriate HTTP status code.
|
|
- Do not log or inspect the caught `error` variable in Worker code — translate to a user-facing message in Chinese.
|
|
- Return `401` for unauthenticated, `403` for unauthorised (missing admin), `400` for bad input, `404` for unknown routes, `405` for wrong method.
|
|
|
|
```typescript
|
|
} 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 `null` body with `{ headers: corsHeaders }` for `OPTIONS` preflight.
|
|
|
|
### Async/Await
|
|
- All handlers are `async function`, returning `Promise<Response>`.
|
|
- Use `async/await` exclusively — no `.then()/.catch()` chains.
|
|
- KV reads are awaited sequentially; use `Promise.all` only 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.mts` uses `defineWorkersConfig` and points at `wrangler.jsonc` for bindings.
|
|
- The `test/` directory has its own `tsconfig.json` (extends root, adds `@cloudflare/vitest-pool-workers` types).
|
|
- Use `env` from `cloudflare:test` to access bindings directly; use `SELF.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`, run `npm run cf-typegen` before writing tests.
|