fix: harden the capture pipeline for production use - #33
Merged
Conversation
Fixes 21 correctness, performance and reliability issues found while auditing the library for real-world usage. Silent data loss and hangs: - Hono and Next.js App Router recorded `requestBody: null` on every POST/PUT/ PATCH, because both read the body after the handler had consumed it. - Streaming responses hung the client in the Hono, Next.js and Elysia adapters, which awaited `.json()` on an open stream before returning the response. - Offline mode and the no-API-key Ollama fallback never worked: the AI SDK's default OpenAI model targets /v1/responses, which Ollama does not implement. - The failure circuit breaker never reopened, so a transient provider outage stopped all documentation until the next deploy. - NestJS never documented responses produced by exception filters. - The Next.js Pages Router created one endpoint (and one AI call) per dynamic id. Robustness: - capture() can no longer throw into the host app's response path, and self-referential bodies terminate instead of overflowing the stack. - Concurrent workers no longer collide on the unique endpoint index after the AI call has already been paid for. - Capture is bounded by default: 256 KB bodies, non-JSON responses skipped, 50 shapes per endpoint, 50 spec versions per endpoint. - Capturers expose flush(), drained on shutdown where the framework has a hook. Performance: - Repeated payload shapes are dropped synchronously, before the queue, so steady-state traffic neither retains bodies nor queues behind a generation. - The queue processes endpoints in parallel, one shape at a time per endpoint. - The size cap stops as soon as the limit is exceeded rather than serializing the whole payload; privacy rules are compiled once per config. - The dashboard reuses one database handle instead of opening a client and re-running the schema DDL per request. BREAKING: the Postgres helpers moved to @easydocs/core/storage/postgres and `postgres` is now an optional peer dependency, so SQLite installs no longer pull in the driver. Configuring storage.type: 'postgres' is unchanged. Verified with build, lint, typecheck and 254 tests (up from 202), plus an end-to-end run of real Express and Hono apps against a stub AI provider. Claude-Session: https://claude.ai/code/session_01GrfumUQ4vFUAgsFYwzDyK8
Every case spawns a fresh Node process to run the CLI bundle, which costs over a second on a CI runner. Three of them shared one `it` and its 5s default budget, which passed locally at ~2s and timed out at 5113ms in CI. Claude-Session: https://claude.ai/code/session_01GrfumUQ4vFUAgsFYwzDyK8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes 21 correctness, performance and reliability issues found while auditing the library for real-world usage. Each fix ships with a regression test.
Silent data loss and hangs
Requestthrows, the catch swallowed it, andrequestBodywas recorded asnullon every POST/PUT/PATCH. The existing Hono test passed only because its handler ignored the body..json()on a clone of the response before returning it. On an open SSE stream that never resolves, so the client received nothing./v1/responses. Ollama (and most OpenAI-compatible gateways) only implement/v1/chat/completions, so every generation failed — breaking bothprivacy.offlineand the no-API-key fallback.tap(), which only fires on success — every response from an exception filter went unrecorded./api/users/1and/api/users/2became separate rows, each paying for its own AI call.Robustness
capture()can no longer throw into the host app's response path, and self-referential bodies terminate instead of overflowing the stack.maxBodySizehad no default, so a stalled provider could let the queue retain unbounded payloads in the host app's heap.flush(), drained on shutdown where the framework has a hook (FastifyonClose, ElysiaonStop, NestJSonApplicationShutdown).ai.model" error rather than an opaque 404.Performance
Breaking
The Postgres helpers (
createPgDB,pgGetAll, …) moved from the package root to@easydocs/core/storage/postgres, andpostgresis now an optional peer dependency loaded on demand — the root re-export pulled the driver into every SQLite install. Postgres users mustnpm i postgres. Configuringstorage.type: 'postgres'is unchanged.Verification
build,lint,typecheckgreen.@easydocs/nextjshad no test setup at all and now has 7.Not addressed
pnpm audit --prodreports 2 pre-existing high CVEs (js-yaml,next > postcss > nanoid), both inapps/dashboarddependencies and untouched by this branch. They will blockpnpm releaseuntil bumped.https://claude.ai/code/session_01GrfumUQ4vFUAgsFYwzDyK8