fix(openapi): use Workers-native fetch for spec URLs#270
Merged
RhysSullivan merged 1 commit intomainfrom Apr 17, 2026
Merged
Conversation
Adding an OpenAPI source via URL hangs on production Cloudflare Workers. Two compounding causes: 1. @apidevtools/swagger-parser fetches URLs via @apidevtools/json-schema-ref-parser's HTTP resolver, which goes through Node's http/https under nodejs_compat and stalls indefinitely on prod workerd. It also inlines every $ref on bundle(), deep-cloning shared schemas — a 16MB spec balloons to hundreds of MB and trips the 128MB Worker cap before it can finish. 2. addSpec wrapped parse + extract inside ctx.transaction, so the pool=1 Hyperdrive Postgres connection held BEGIN open across the network fetch. Changes: - parse.ts: drop @apidevtools/swagger-parser entirely. Add fetchSpecText(url) that uses @effect/platform's HttpClient with a 20s Effect.timeout — pluggable via FetchHttpClient.layer (Workers-native) or a test-injected fetch. parse() is now JSON.parse + YAML fallback + 3.x validation; no ref resolution, because DocResolver (openapi-utils.ts) already resolves $refs lazily and normalizeOpenApiRefs preserves them through to the $defs table. Removed the manual resolveRefsInPlace walker — same deep-clone memory problem. - plugin.ts: resolveSpecText(config.spec) runs with httpClientLayer provided; parse + extract run BEFORE ctx.transaction. Only the three storage writes (upsertSource, sources.register, definitions.register) stay inside the tx, so Hyperdrive's single connection isn't held during network I/O. detect() + previewSpec() get the same treatment. - preview.ts / preview-oauth2.test.ts / real-specs.test.ts: wrap previewSpec with FetchHttpClient.layer where tests call it directly. real-specs.test.ts also strips the three in-memory-adapter addSpec tests — equivalent coverage lives in the cloud-app integration suite after this stack lands. - package.json / bun.lock: drop @apidevtools/swagger-parser. openapi test suite: 30/30 pass, 2.4s (was 12.4s with swagger-parser).
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | bdbb8e6 | Commit Preview URL Branch Preview URL |
Apr 17 2026, 06:59 PM |
This was referenced Apr 17, 2026
Owner
Author
@executor/sdk
@executor/plugin-file-secrets
@executor/plugin-google-discovery
@executor/plugin-graphql
@executor/plugin-keychain
@executor/plugin-mcp
@executor/plugin-oauth2
@executor/plugin-onepassword
@executor/plugin-openapi
@executor/plugin-workos-vault
executor
commit: |
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.

Adding an OpenAPI source via URL hangs on production Cloudflare Workers.
Two compounding causes:
@apidevtools/swagger-parser fetches URLs via @apidevtools/json-schema-ref-parser's
HTTP resolver, which goes through Node's http/https under nodejs_compat and
stalls indefinitely on prod workerd. It also inlines every $ref on bundle(),
deep-cloning shared schemas — a 16MB spec balloons to hundreds of MB and
trips the 128MB Worker cap before it can finish.
addSpec wrapped parse + extract inside ctx.transaction, so the pool=1
Hyperdrive Postgres connection held BEGIN open across the network fetch.
Changes:
parse.ts: drop @apidevtools/swagger-parser entirely. Add fetchSpecText(url)
that uses @effect/platform's HttpClient with a 20s Effect.timeout — pluggable
via FetchHttpClient.layer (Workers-native) or a test-injected fetch. parse()
is now JSON.parse + YAML fallback + 3.x validation; no ref resolution, because
DocResolver (openapi-utils.ts) already resolves $refs lazily and
normalizeOpenApiRefs preserves them through to the $defs table. Removed the
manual resolveRefsInPlace walker — same deep-clone memory problem.
plugin.ts: resolveSpecText(config.spec) runs with httpClientLayer provided;
parse + extract run BEFORE ctx.transaction. Only the three storage writes
(upsertSource, sources.register, definitions.register) stay inside the tx,
so Hyperdrive's single connection isn't held during network I/O. detect() +
previewSpec() get the same treatment.
preview.ts / preview-oauth2.test.ts / real-specs.test.ts: wrap previewSpec
with FetchHttpClient.layer where tests call it directly. real-specs.test.ts
also strips the three in-memory-adapter addSpec tests — equivalent coverage
lives in the cloud-app integration suite after this stack lands.
package.json / bun.lock: drop @apidevtools/swagger-parser.
openapi test suite: 30/30 pass, 2.4s (was 12.4s with swagger-parser).