ID |
|
|---|---|
Status |
Backlog |
Bucket |
feature |
Priority |
5 |
Theme |
structural-refactor |
Implement @experimental_constructType
The @experimental_constructType(selection: "…") directive is declared in directives.graphqls and stripped from the emitted schema by SchemaDirectiveRegistry, but no classifier, model carrier, or emitter exists for it yet.
What it does
Allows a schema field to be resolved by projecting raw database columns onto a non-table-backed GraphQL type, without requiring a Java backing class or a @record parent. The selection argument is a comma-separated graphqlField: SQL_COLUMN mapping string, e.g.:
fullName: String @experimental_constructType(selection: "firstName: FIRST_NAME, lastName: LAST_NAME")
At generation time the generator parses the selection string and emits a DSL.select(…) projection that feeds the named columns into the type’s fields.
What exists
-
Directive definition in
directives.graphqls:341 -
SchemaDirectiveRegistryalready lists it as generator-only (it is stripped correctly) -
selection/package (GraphQLSelectionParser,Lexer,Token,TokenKind,ParsedField,ParsedArgument,ParsedValue) provides the generation-time parser for theselectionstring; this was confirmed as the correct home by the R30 audit
Work needed
-
Classifier: read
@experimental_constructTypeinFieldBuilder(or a newConstructTypeDirectiveResolver); parseselectionviaGraphQLSelectionParser; produce a newGraphitronFieldvariant (e.g.ConstructedTypeField) carrying the parsed field-to-column bindings -
Model: sealed variant with column bindings; validate that every named SQL column exists in the parent table’s jOOQ catalog
-
Emitter: emit a
DSL.select(col1.as("graphqlField1"), col2.as("graphqlField2"), …)projection in the generated$fieldsmethod body -
Tests: unit-tier pipeline cases; execution-tier test against Sakila schema
Out of scope for this item
Renaming the @experimental_ prefix once the feature is stable (separate stabilisation step).
Related
-
R249 (
nested-argmapping-syntax) is the input-side sibling: it wiresGraphQLSelectionParserinto@argMapping’s right-hand side so that `paramName: { fieldA: input.x, fieldB: input.other.y, … }parses through the sameObjectValuearm. Both items lean on theselection/package’s parser; this item drives the output-side projection, R249 drives the input-side construction. -
R238 (
methodcall-walker-carrier) lands the carrier model with paths onValueShapeleaves, which represents R249’s nested-form construction uniformly with the default-mapping case.