Generated: 2026-05-26
Branch: main (unborn; no local commits at generation time)
Commit: none
Node.js/TypeScript Fastify service that accepts a Feishu/Lark Docx link, wiki link, or raw docx token and synchronously returns text highlight background-color data from official Feishu/Lark OpenAPI. V1 is request/response only: parse input, authenticate locally, call Lark APIs, traverse blocks, extract colors, return JSON.
labs-lark-doc-color-counter/
├── src/ # Fastify API, Lark client, parsing, extraction
├── tests/ # Vitest contracts for auth, parser, client, endpoint, userscript
├── scripts/ # Tampermonkey companion; see scripts/AGENTS.md
├── package.json # npm scripts and dependency boundary
├── tsconfig*.json # strict NodeNext runtime/build configs
└── .env.example # committed local config template
| Task | Location | Notes |
|---|---|---|
| Start server | src/server.ts |
Loads config, builds app, listens on 0.0.0.0. |
| Wire HTTP API | src/app.ts |
Fastify factory, auth hook, POST /v1/extract, error mapping. |
| Validate env | src/config.ts |
Requires API_TOKEN, LARK_APP_ID, LARK_APP_SECRET; PORT defaults to 3000. |
| Protect API | src/auth.ts |
Static Authorization: Bearer <API_TOKEN> check before route logic. |
| Parse input | src/documentParser.ts |
Supports /docx/, /wiki/, raw docx tokens; rejects other types. |
| Resolve and fetch | src/documentService.ts |
Converts wiki nodes to docx identities and walks all block pages. |
| Call Lark APIs | src/larkClient.ts |
Tenant token, wiki get_node, docx block pages with page_size=500. |
| Extract highlights | src/extractor.ts |
Recursive scan for text_run.text_element_style.background_color. |
| Map colors | src/textBackgroundColors.ts |
Official text background codes 0-15; code 0 is no fill. |
| Browser helper | scripts/feishu-highlight-counter.user.js |
Tested Tampermonkey UI/client surface. |
| Test helpers | tests/helpers.ts |
Shared testConfig and queued mock fetch. |
| Symbol | Type | Location | Role |
|---|---|---|---|
createApp / buildApp |
function/export | src/app.ts |
Constructs injectable Fastify app for server and tests. |
createAuthHook |
function | src/auth.ts |
Rejects missing/invalid service token before Lark calls. |
loadConfig |
function | src/config.ts |
Loads dotenv only for real process env and validates config. |
parseDocumentInput |
function | src/documentParser.ts |
Normalizes supported URL/token inputs into docx/wiki variants. |
extractDocument |
function | src/documentService.ts |
Main service workflow from parsed input to extraction result. |
LarkClient |
class | src/larkClient.ts |
Low-level Feishu/Lark OpenAPI boundary with token caching. |
extractHighlights |
function | src/extractor.ts |
Produces segments, color summary, and totals from unknown blocks. |
TEXT_BACKGROUND_COLOR_MAP |
constant | src/textBackgroundColors.ts |
Color metadata returned in endpoint responses. |
- ESM package: local TypeScript imports use emitted
.jsspecifiers. - TypeScript is strict with
noUncheckedIndexedAccessandexactOptionalPropertyTypes; guard indexed reads and omit optional properties instead of assigningundefined. - Tests are top-level
tests/**/*.test.ts, Vitest globals, Node environment. - Build includes only
src/**/*.ts;tests/andscripts/are verified by tests but not emitted bynpm run build. - Keep fetch injectable through
FetchFn/constructor options; tests assert outbound URLs, methods, headers, and request bodies. - Prefer source-shaped tests: parser tests for input shape, client tests for API mapping, service tests for orchestration, endpoint tests for response JSON.
- No async job queue, background worker, persistent job storage, or V1 rate limiting.
- No browser DOM scraping, page scraping, or exported DOCX parsing for the main extraction path.
- Do not let unsupported document types fall back to another mechanism; return a typed 400.
- Do not accept
GET /v1/extract; document links/tokens stay in POST body, not query strings. - Do not call Feishu/Lark APIs before service-token authentication succeeds.
- Do not commit
.envor real credentials. Never logAPI_TOKEN,LARK_APP_SECRET, tenant access tokens, or bearer headers. - Do not weaken tests that assert auth-before-fetch, wiki-docx rejection, pagination, or userscript contract.
AppErrorcarries HTTP status and stable error code; Fastify error handler serializes{ error: { code, message } }.LarkClientcaches tenant access tokens until a 30-minute refresh window and treats nonzero Larkcodeaslark_api_error.- Paginated docx blocks require
has_morepluspage_token; missing next token is a 502 upstream-shape error. - Extractor accepts unknown OpenAPI block shapes, recursively visits nested values, and reads either
text_run.contentortext_run.text. - Background color code
0means no fill and is skipped; unknown nonzero color codes returnUNKNOWNmetadata rather than failing extraction.
npm ci
npm run test
npm run typecheck
npm run build
npm run dev
npm start- Dependencies must be installed before validation; without
node_modules,tsccannot resolve Node/Vitest types andvitestis unavailable. package-lock.jsoncurrently resolves packages throughregistry.npmmirror.com; keep CI/network expectations in mind..env.exampleis the only committed env template..envand.env.*are ignored except.env.example.- Existing tests also lock down the userscript path, metadata, supported domains, POST payload, token storage key, color-name mapping JSON, bottom-left panel anchor, and auto-refresh overlay behavior.