Skip to content

fix: don't stub every field when a mapper type is unresolvable - #455

Merged
eddeee888 merged 1 commit into
eddeee888:masterfrom
GlebYavorski:fix/smart-unresolvable-mapper-stub-injection
Sep 22, 2026
Merged

eddeee888 merged 1 commit into
eddeee888:masterfrom
GlebYavorski:fix/smart-unresolvable-mapper-stub-injection

Conversation

@GlebYavorski

Copy link
Copy Markdown
Contributor

Summary

Fixes #446.

When a mapper aliases a type whose import cannot be resolved (a TypeScript error type — e.g. a Prisma/generated client that hasn't been generated yet, or a module not installed on a fresh checkout), fixObjectTypeResolvers ('smart' and 'fast') treated the mapper as having zero fields and injected a resolver is required because … does not stub for every field of the schema type. This silently overwrites hand-maintained resolver files with stubs that return Promise<void> and break tsc.

Root cause

getNodePropertyMap derives the mapper's properties from node.getType().getProperties(), which returns [] for an error type. The generator couldn't tell "mapper genuinely has no fields" apart from "mapper type could not be resolved", so every field took the if (!mapperProperty) branch and got a stub.

Fix

  • Add isNodeTypeUnresolved, which detects the TypeScript error type (intrinsic type named error). This is distinct from a real any (intrinsicName === 'any') and from an empty object type (not an intrinsic type at all), so it does not misfire on those.
  • In both the smart and fast paths, when the mapper's declaration node is unresolved, skip stub generation for that mapper (leaving existing resolvers untouched) and emit a logger.warn naming the mapper, so the real problem — the unresolved import — surfaces.
  • Genuinely empty mappers (type FooMapper = {}) still generate stubs as before.

Tests

  • Unit tests for isNodeTypeUnresolved covering: unresolvable import → true; empty {} → false; explicit any → false; resolved import → false; undefined node → false.
  • Integration tests for getGraphQLObjectTypeResolversToGenerate (both smart and fast): an unresolvable mapper produces no stubs and warns once; a genuinely empty mapper still stubs every field and does not warn.

nx test/lint/build typescript-resolver-files all pass. Existing e2e snapshots are unaffected (behavior only changes for unresolvable mappers, which no fixture has).

A changeset (patch) is included.

@changeset-bot

changeset-bot Bot commented Jul 16, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c61e9f2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@eddeee888/gcg-typescript-resolver-files Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

`fixObjectTypeResolvers` ('smart' and 'fast') built a mapper's property
set from `getProperties()`, which returns `[]` for a TypeScript *error
type* (an unresolvable import, e.g. a client that hasn't been generated
yet). An error type was therefore indistinguishable from an empty
mapper, so a resolver stub was injected for every field, silently
overwriting hand-maintained resolver files with broken `Promise<void>`
stubs.

Detect the error type via `isNodeTypeUnresolved` before deriving the
property map; when the mapper is unresolvable, skip stub generation
(leaving existing resolvers untouched) and emit a warning naming the
mapper so the real problem — the unresolved import — surfaces.
Genuinely empty mappers (`type FooMapper = {}`) still stub as before.

Fixes eddeee888#446

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@eddeee888
eddeee888 force-pushed the fix/smart-unresolvable-mapper-stub-injection branch from 9a5e528 to c61e9f2 Compare September 22, 2026 12:50
Repository owner deleted a comment from github-actions Bot Sep 22, 2026

@eddeee888 eddeee888 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @GlebYavorski !
I'll look to release this soon

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.

fixObjectTypeResolvers: 'smart' treats an unresolvable mapper type as an empty mapper and injects a stub for every field

2 participants