Skip to content

feat: add createFetch to runtime, remove @constructive-io/node#1033

Merged
pyramation merged 6 commits intomainfrom
feat/simple-localhost-fetch
Apr 28, 2026
Merged

feat: add createFetch to runtime, remove @constructive-io/node#1033
pyramation merged 6 commits intomainfrom
feat/simple-localhost-fetch

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

@pyramation pyramation commented Apr 28, 2026

Summary

Simple alternative to #1025. Adds createFetch() to @constructive-io/graphql-query/runtime (already imported by every generated client) and deletes @constructive-io/node — the SDK now works everywhere without a separate Node-specific package.

What createFetch() does:

  • In Node.js: uses node:http/node:https for *.localhost URLs, fixing both DNS resolution (ENOTFOUND) and Host header preservation (silently dropped by undici). Delegates all other URLs to globalThis.fetch.
  • In browsers: returns globalThis.fetch as-is (browsers handle *.localhost natively).
  • Result is cached — safe to call repeatedly.

What changed:

  1. graphql/query/src/runtime/localhost-fetch.ts — new ~100 line file with createFetch(), isLocalhostSubdomain(), FetchFunction type.
  2. graphql/query/src/runtime/index.ts — re-exports createFetch and FetchFunction.
  3. graphql/codegen/.../templates/orm-client.ts — imports createFetch from runtime. FetchAdapter defaults to createFetch(). New OrmClientConfig.fetch? for custom fetch injection.
  4. Regenerated all 13 SDK client files.
  5. Deleted sdk/constructive-node/NodeHttpAdapter is now redundant since FetchAdapter uses createFetch() by default.

Why not #1025? That PR bakes ~200 lines into the codegen template (node:http, new Function, runtime detection). This PR puts the logic in the runtime package that generated code already depends on — update one file, no regeneration needed.

BREAKING: @constructive-io/node is removed. Users should import from @constructive-io/sdk directly — no adapter setup needed.

Review & Testing Checklist for Human

  • Verify createClient({ endpoint: 'http://auth.localhost:3000/graphql' }) resolves correctly from Node.js (no ENOTFOUND)
  • Verify the Host header is preserved for subdomain routing (e.g. auth.localhost routes to the auth schema)
  • Verify browser SDK usage is unaffected (createFetch returns globalThis.fetch, no-op)
  • Check that no external consumers depend on @constructive-io/node before merging

Notes

  • Zero new dependencies — createFetch lives in @constructive-io/graphql-query/runtime
  • The @constructive-io/fetch package in dev-utils is still available as a standalone if needed
  • Migration for existing @constructive-io/node users: replace import { NodeHttpAdapter } from '@constructive-io/node' + createClient({ adapter }) with just import { createClient } from '@constructive-io/sdk' + createClient({ endpoint })

Link to Devin session: https://app.devin.ai/sessions/0e3a5bf6765a4c979b64ef786a813225
Requested by: @pyramation

Simple alternative to #1025 — adds *.localhost DNS rewriting and a
fetch injection point to OrmClientConfig without pulling in node:http,
new Function(), or runtime environment detection.

Changes:
- localhostFetch(): ~20-line wrapper that rewrites *.localhost URLs to
  plain localhost and sets the Host header (best-effort) using
  globalThis.fetch. Zero dependencies, works in all runtimes.
- FetchAdapter: accepts optional fetchFn (defaults to localhostFetch).
- OrmClientConfig: new fetch? option lets callers inject custom fetch
  (e.g. @constructive-io/node for full Host header support via node:http,
  or a mock for tests).
- Regenerated all SDK client files.
- Added codegen tests for the new config surface and localhost rewriting.
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Replace the inlined localhostFetch wrapper with an import from
@constructive-io/fetch (dev-utils#81). The package handles:
- *.localhost DNS rewriting via node:http (fixes ENOTFOUND)
- Host header preservation (fixes silent drop by undici)
- Automatic passthrough for non-localhost URLs and browsers

This moves the fetch logic to a shared library so it can be
iterated on in one place rather than being baked into every
generated client file.

Added @constructive-io/fetch ^0.1.0 as a dependency to all SDK
packages (constructive-sdk, constructive-react, constructive-cli,
migrate-client).
The CLI E2E test generates ORM code into a temp directory and runs it
in a subprocess. The generated client.ts now imports createFetch from
@constructive-io/fetch, so the package must be resolvable via NODE_PATH.

Added to both the runtimeDeps array in cli-e2e.test.ts and as a
dependency in graphql/server-test/package.json.
…tive-io/fetch dep

Instead of adding @constructive-io/fetch as an external dependency to
every SDK package, embed the localhost-aware fetch directly in
@constructive-io/graphql-query/runtime — which every generated client
already imports. Zero new dependencies for consumers.

- Added graphql/query/src/runtime/localhost-fetch.ts
- Re-exported createFetch from runtime/index.ts
- Updated codegen template to import from runtime
- Removed @constructive-io/fetch from all SDK + server-test package.json
- Regenerated all 13 SDK client files
No longer needed — createFetch() in @constructive-io/graphql-query/runtime
handles *.localhost DNS + Host header for Node.js automatically. The SDK
now works everywhere (Node, browser, Deno, Bun) without a separate
Node-specific package.

BREAKING: @constructive-io/node is removed. Users should import from
@constructive-io/sdk directly — no adapter setup needed.
@devin-ai-integration devin-ai-integration Bot changed the title feat(codegen): add localhostFetch wrapper and fetch? config option feat: add createFetch to runtime, remove @constructive-io/node Apr 28, 2026
@pyramation pyramation merged commit dc20423 into main Apr 28, 2026
53 checks passed
@pyramation pyramation deleted the feat/simple-localhost-fetch branch April 28, 2026 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant