Skip to content

Conversation

@pyramation
Copy link
Contributor

@pyramation pyramation commented Jan 26, 2026

Summary

Fixes two issues in the fetch process for GraphQL schema introspection (build-time) and adds a new browserCompatible config option for generated runtime code.

Build-time fixes (fetch-schema.ts)

Problem 1: Wrong fetch implementation - The code was using Node.js's global fetch() instead of undici's fetch(), which meant the dispatcher option (used for custom DNS resolution) was being ignored.

Problem 2: Incorrect DNS lookup callback - The custom DNS lookup function wasn't handling the all: true option correctly. When opts.all is true, the callback expects an array of address objects [{address, family}], not individual parameters (err, address, family).

New feature: browserCompatible option for generated code

Added a new config option to control the fetch implementation in generated runtime code:

{
  browserCompatible?: boolean; // default: true
}
  • true (default): Generated code uses native W3C fetch API (works in browsers and Node.js)
  • false: Generated code uses undici fetch with dispatcher support for localhost DNS resolution (Node.js only - enables proper *.localhost subdomain resolution on macOS)

Updates since last revision

Refactored code generation to use template files instead of string-based generation:

  • Created templates/ directory containing all static runtime code as real TypeScript files
  • Templates: client.browser.ts, client.node.ts, orm-client.ts, select-types.ts, query-builder.ts
  • Generators now read from template files at codegen time
  • Templates are excluded from TypeScript compilation (they contain imports that only exist in generated output context)
  • Build script copies templates to dist/ for production use

Benefits: Templates are properly typed, easier to maintain, and have IDE support.

Review & Testing Checklist for Human

  • Verify templates are copied to dist: After pnpm build, check that dist/core/codegen/templates/ contains all 5 template files
  • Test localhost subdomain resolution (build-time): Run cnc codegen against a GraphQL endpoint using a localhost subdomain (e.g., http://api.localhost:3000/graphql) on macOS
  • Test browserCompatible: false: Generate code with browserCompatible: false and verify the generated client.ts includes undici imports and localhost agent logic
  • Verify generated code compiles: When browserCompatible: false, ensure the generated code compiles and runs correctly in a Node.js environment with undici installed
  • Test package installation: Install the built package in a test project and verify codegen works (templates found at runtime)

Recommended test plan:

  1. Run pnpm build and verify dist/core/codegen/templates/ exists with all template files
  2. Run cnc codegen against http://api.localhost:3000/graphql on macOS to test build-time fix
  3. Generate code with both browserCompatible: true and browserCompatible: false, inspect the output files

Notes

  • No unit tests were added for the browserCompatible option or template file reading logic
  • The localhost DNS resolution logic is duplicated in build-time code and generated runtime code (when browserCompatible: false)
  • When using browserCompatible: false, users must have undici installed as a runtime dependency
  • 2 test snapshots were updated due to formatting differences between template files and previous string templates
  • Link to Devin run: https://app.devin.ai/sessions/fcc3cfc6448d4862bb8ce07110e1f27f
  • Requested by: Dan Lynch (@pyramation)

Problem 1: The code was using Node.js's global fetch() instead of undici's
fetch(), which meant the dispatcher option was being ignored. Fixed by
importing and using fetch from undici.

Problem 2: The custom DNS lookup function wasn't handling the all: true
option correctly. When opts.all is true, the callback expects an array of
address objects [{address, family}], not individual parameters. Fixed by
checking opts.all and returning the appropriate format.
@devin-ai-integration
Copy link
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

Add browserCompatible option to GraphQLSDKConfigTarget:
- When true (default): generated code uses native W3C fetch (browser-compatible)
- When false: generated code uses undici fetch with dispatcher support
  for localhost DNS resolution (Node.js only)

This allows users to generate Node.js-specific code that properly resolves
*.localhost subdomains on macOS, while maintaining browser compatibility
by default.
@devin-ai-integration devin-ai-integration bot changed the title fix(graphql-codegen): use undici fetch and fix DNS lookup callback fix(graphql-codegen): use undici fetch and add browserCompatible option Jan 26, 2026
- Create templates/ directory for all static runtime code
- Move client.browser.ts and client.node.ts (for browserCompatible option)
- Move orm-client.ts (OrmClient, FetchAdapter, GraphQLRequestError)
- Move select-types.ts (ConnectionResult, PageInfo, DeepExact, etc.)
- Move query-builder.ts from orm/ to templates/
- Update generators to read from template files instead of strings
- Simplify path resolution (templates at same relative path in src/ and dist/)
- Exclude templates/ from TypeScript compilation (they have generated imports)
- Update build script to copy templates to dist/

Benefits:
- Templates are real TypeScript files with proper type checking
- Easier to maintain and review
- IDE support (autocomplete, error highlighting)
- Clear separation between static runtime code and dynamic generation
@pyramation pyramation merged commit 3b2c659 into main Jan 27, 2026
50 checks passed
@pyramation pyramation deleted the devin/1769461089-fix-fetch-dns-lookup branch January 27, 2026 00:57
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.

2 participants