Summary
pylon pull emits branded primitives:
type String = string & {readonly brand?: unique symbol};
type Boolean = boolean & {readonly brand?: unique symbol};
type Number = number & {readonly brand?: unique symbol};
// …7 in total
The schema builder then treats the brand marker as structure and turns it into real GraphQL object types. They end up in the published SDL as orphans.
Reproduction
pylon pull <remote> -n lokalis
- Use the registry in a gateway and build.
- Introspect the resulting schema:
Success → brand: Brand
Brand → description
ToPrimitive_1315 → description
Confirmed these are artifacts, not real types:
- the remote has no
Success type — __type(name: "Success") returns null against it;
- the application defines none of the three;
Success is referenced only by itself (Success.brand); Brand and ToPrimitive_1315 are referenced by nothing at all.
ToPrimitive_1315 looks like Symbol.toPrimitive reached through the intersection, and the numeric suffix like a synthesized-name counter.
Impact
Cosmetic but public: three meaningless types in a published API surface, one of them named Success, which reads like something a client is meant to use. They also make "which types does my gateway expose?" harder to answer — they were noise while auditing exactly that (see #114).
Proposal
Skip symbol-keyed and unique symbol members when converting TS types to GraphQL, so an intersection used purely for branding contributes nothing. Alternatively have pull emit nominal aliases that carry no structural members, since the brand is only there to keep the generated primitives distinct in TS and has no meaning in the schema.
Summary
pylon pullemits branded primitives:The schema builder then treats the brand marker as structure and turns it into real GraphQL object types. They end up in the published SDL as orphans.
Reproduction
pylon pull <remote> -n lokalisConfirmed these are artifacts, not real types:
Successtype —__type(name: "Success")returnsnullagainst it;Successis referenced only by itself (Success.brand);BrandandToPrimitive_1315are referenced by nothing at all.ToPrimitive_1315looks likeSymbol.toPrimitivereached through the intersection, and the numeric suffix like a synthesized-name counter.Impact
Cosmetic but public: three meaningless types in a published API surface, one of them named
Success, which reads like something a client is meant to use. They also make "which types does my gateway expose?" harder to answer — they were noise while auditing exactly that (see #114).Proposal
Skip symbol-keyed and
unique symbolmembers when converting TS types to GraphQL, so an intersection used purely for branding contributes nothing. Alternatively havepullemit nominal aliases that carry no structural members, since the brand is only there to keep the generated primitives distinct in TS and has no meaning in the schema.