Skip to content

fix(graphile-schema): hybrid deepmerge — pluck extends/pgServices, deepmerge the rest#901

Merged
pyramation merged 1 commit into
mainfrom
devin/1774510734-forward-all-graphile-preset-keys
Mar 26, 2026
Merged

fix(graphile-schema): hybrid deepmerge — pluck extends/pgServices, deepmerge the rest#901
pyramation merged 1 commit into
mainfrom
devin/1774510734-forward-all-graphile-preset-keys

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

Summary

Follow-up to #900. The previous fix removed deepmerge entirely and only forwarded extends and plugins from opts.graphile, silently dropping any other preset keys (e.g. disablePlugins, schema, gather).

This restores deepmerge but uses a hybrid approach: destructure out extends and pgServices (the two keys that cause stack overflow when deep-cloned) and compose them via Graphile's native extends mechanism, while deepmerging the remaining safe keys.

const { extends: callerExtends, pgServices: _pgServices, ...callerRest } = opts.graphile ?? {}

const preset = {
  ...deepmerge({}, callerRest),        // safe keys: plugins, disablePlugins, schema, gather, etc.
  extends: [ConstructivePreset, ...(callerExtends ?? [])],   // native composition
  pgServices: [makePgService({ pool, schemas })],             // always ours
}

Review & Testing Checklist for Human

  • deepmerge({}, callerRest) clones plugin objects: If a caller passes plugins: [SomePlugin] directly in opts.graphile, deepmerge will deep-clone SomePlugin, breaking object identity. Graphile deduplicates plugins by identity (===), so cloned plugins could be applied twice. Verify whether any call site passes plugins this way — if so, plugins should be plucked out alongside extends/pgServices and composed by reference.
  • Confirm no other non-serializable keys exist: The assumption is that only extends (preset tree) and pgServices (pg Pool) contain non-cloneable objects. If any caller passes other keys with class instances or EventEmitters, deepmerge would still break. Grep buildSchemaSDL usage across constructive-db and constructive-hub.
  • Lockfile diff is cosmetic: The pnpm-lock.yaml change is ~5000 lines but is 99.9% pnpm reformatting (multi-line resolution: blocks → single-line). The only functional change is re-adding deepmerge@4.3.1. Skim, don't line-review.
  • Re-run the failing constructive-hub CI after publishing updated graphile-schema to confirm all 7 API schema generations pass end-to-end.

Notes

  • Verified locally: all 6 API targets (public, admin, auth, app, objects, migrate) build SDL successfully with NodeTypeRegistryPreset using this hybrid approach.
  • deepmerge({}, callerRest) is effectively a deep clone of callerRest. 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

…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.
@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

@pyramation pyramation merged commit b00016e into main Mar 26, 2026
43 checks passed
@pyramation pyramation deleted the devin/1774510734-forward-all-graphile-preset-keys branch March 26, 2026 07:51
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