Skip to content

v5: Safe way to rename / remove / relocate fields #2841

@zxpectre

Description

@zxpectre

v5: Safe way to rename / remove / relocate fields (e.g. move totalCount into aggregate.count for Hasura-style aggregates)

Hi 👋. I’m using PostGraphile v5 with @graphile/pg-aggregates and Grafast, and I’m trying to build a plugin that reshapes the entire schema for connection types to look more like Hasura’s aggregate API.

Concretely, for any GraphQL object type that:

  • is backed by a ConnectionStep (i.e. Self.extensions.grafast.assertStep.$$export.exportName === "ConnectionStep"), and
  • exposes one of the aggregate fields added by @graphile/pg-aggregates (e.g. aggregates, aggregate, groupedAggregates),

I’d like to be able to:

  1. Rename fields (e.g. rename a connection root field or aggregatesaggregate).
  2. Remove fields at the connection level (e.g. hide totalCount / count from the top level).
  3. Clone / relocate fields while preserving their Grafast plan (e.g. move totalCount so that it is also available as aggregate.count inside the aggregate container).

The end goal is a Hasura-like shape such as:

foo_aggregate {
  aggregate {
    count
    sum { ... }
    avg { ... }
  }
  groupedAggregate { ... }
}

…where aggregate.count behaves exactly like the existing totalCount/count on the connection (same semantics, same plan), and ideally we can optionally drop the top-level totalCount field.

What I tried

I experimented with:

  • schema.hooks.GraphQLObjectType_fields (v5 hook API), and
  • processSchema(...) post-build transformations, and
  • copying the GraphQLField / GraphQLFieldConfig and/or extensions.grafast from the connection’s totalCount field into the aggregate container type.

This “works” at the type level (the new aggregate.count field appears in the schema), but at runtime it tends to break the aggregate object resolution – aggregate becomes null – because the copied plan was written assuming the parent step is the connection step, not the aggregate step.

In other words, naïvely cloning the field or its plan isn’t safe without deeper knowledge of the internal Step graph.

Request

Would it be possible to have either:

  • A documented pattern / example plugin that shows how to:

    • rename / hide fields on ConnectionStep-backed types, and
    • expose a count field inside the aggregate container that reuses the existing connection-level totalCount logic safely, or
  • A first-class option in @graphile/pg-aggregates / core that exposes a Hasura-style aggregate.count (optionally also allowing the top-level totalCount to be removed), or

  • A small API hook that lets a plugin get from the aggregate Step back to the underlying connection Step (so a custom aggregate.count plan can delegate to the same logic as totalCount without relying on internal, undocumented assumptions)?

I’m specifically trying to avoid:

  • casting everything to any and poking at private properties, and
  • brittle hacks that rely on internal Step structures that may change.

A supported way to do “rename / remove / relocate field while preserving its Grafast plan” for connection/aggregate types would make Hasura-style compatibility much easier to maintain.

Thanks a lot for any guidance or API hooks you can provide 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    🌳 Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions