fix(graphile-schema): hybrid deepmerge — pluck extends/pgServices, deepmerge the rest#901
Merged
pyramation merged 1 commit intoMar 26, 2026
Conversation
…epmerge the rest Restore deepmerge for safe scalar/object preset keys (plugins, disablePlugins, schema, gather, etc.) but pluck out extends and pgServices and compose them via Graphile native mechanism. This avoids the stack overflow from deep-cloning the PostGraphile preset tree and pg Pool objects, while still forwarding all caller- provided preset keys.
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
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.
Summary
Follow-up to #900. The previous fix removed
deepmergeentirely and only forwardedextendsandpluginsfromopts.graphile, silently dropping any other preset keys (e.g.disablePlugins,schema,gather).This restores
deepmergebut uses a hybrid approach: destructure outextendsandpgServices(the two keys that cause stack overflow when deep-cloned) and compose them via Graphile's nativeextendsmechanism, while deepmerging the remaining safe keys.Review & Testing Checklist for Human
deepmerge({}, callerRest)clones plugin objects: If a caller passesplugins: [SomePlugin]directly inopts.graphile, deepmerge will deep-cloneSomePlugin, breaking object identity. Graphile deduplicates plugins by identity (===), so cloned plugins could be applied twice. Verify whether any call site passespluginsthis way — if so,pluginsshould be plucked out alongsideextends/pgServicesand composed by reference.extends(preset tree) andpgServices(pg Pool) contain non-cloneable objects. If any caller passes other keys with class instances or EventEmitters, deepmerge would still break. GrepbuildSchemaSDLusage acrossconstructive-dbandconstructive-hub.pnpm-lock.yamlchange is ~5000 lines but is 99.9% pnpm reformatting (multi-lineresolution:blocks → single-line). The only functional change is re-addingdeepmerge@4.3.1. Skim, don't line-review.graphile-schemato confirm all 7 API schema generations pass end-to-end.Notes
NodeTypeRegistryPresetusing this hybrid approach.deepmerge({}, callerRest)is effectively a deep clone ofcallerRest. If callers only ever pass simple keys, a plain spread (...callerRest) would suffice and avoid the deepmerge dependency entirely. Worth considering whether the deep clone adds value here.Link to Devin session: https://app.devin.ai/sessions/6c7e6bf137a34786827fc77a43a7a84a
Requested by: @pyramation