11import {
2+ resolveUsages ,
3+ UsageFlags ,
24 type Enum ,
35 type Model ,
46 type Namespace ,
57 type Operation ,
68 type Program ,
79 type Scalar ,
10+ type UsageTracker ,
811} from "@typespec/compiler" ;
912import { $ } from "@typespec/compiler/typekit" ;
1013import {
@@ -47,9 +50,20 @@ const graphqlMutationRegistry = {
4750 Intrinsic : SimpleIntrinsicMutation ,
4851} ;
4952
53+ /**
54+ * Result of mutating a model with usage awareness.
55+ * Contains separate mutations for input and output variants when applicable.
56+ */
57+ export interface ModelMutationResult {
58+ /** The input variant mutation (with "Input" suffix), if the model is used as input */
59+ input ?: GraphQLModelMutation ;
60+ /** The output variant mutation (no suffix), if the model is used as output */
61+ output ?: GraphQLModelMutation ;
62+ }
63+
5064/**
5165 * GraphQL mutation engine that applies GraphQL-specific transformations
52- * to TypeSpec types, such as name sanitization.
66+ * to TypeSpec types, such as name sanitization and input/output splitting .
5367 */
5468export class GraphQLMutationEngine {
5569 /**
@@ -58,16 +72,55 @@ export class GraphQLMutationEngine {
5872 */
5973 private engine ;
6074
61- constructor ( program : Program , _namespace : Namespace ) {
75+ /** Usage tracker for types in the namespace */
76+ private usageTracker : UsageTracker ;
77+
78+ constructor ( program : Program , namespace : Namespace ) {
6279 const tk = $ ( program ) ;
6380 this . engine = new MutationEngine ( tk , graphqlMutationRegistry ) ;
81+
82+ // Resolve usages once at construction time
83+ this . usageTracker = resolveUsages ( namespace ) ;
84+ }
85+
86+ /**
87+ * Get the usage flags for a model.
88+ */
89+ getUsage ( model : Model ) : UsageFlags {
90+ const isInput = this . usageTracker . isUsedAs ( model , UsageFlags . Input ) ;
91+ const isOutput = this . usageTracker . isUsedAs ( model , UsageFlags . Output ) ;
92+
93+ if ( isInput && isOutput ) {
94+ return UsageFlags . Input | UsageFlags . Output ;
95+ } else if ( isInput ) {
96+ return UsageFlags . Input ;
97+ } else if ( isOutput ) {
98+ return UsageFlags . Output ;
99+ }
100+ return UsageFlags . None ;
64101 }
65102
66103 /**
67- * Mutate a model, applying GraphQL name sanitization.
104+ * Mutate a model with usage awareness.
105+ * Returns separate input/output mutations based on how the model is used.
68106 */
69- mutateModel ( model : Model ) : GraphQLModelMutation {
70- return this . engine . mutate ( model , new GraphQLMutationOptions ( ) ) as GraphQLModelMutation ;
107+ mutateModel ( model : Model ) : ModelMutationResult {
108+ const usage = this . getUsage ( model ) ;
109+ const result : ModelMutationResult = { } ;
110+
111+ // Create output mutation if used as output (or no usage info)
112+ if ( usage & UsageFlags . Output || usage === UsageFlags . None ) {
113+ const outputOptions = new GraphQLMutationOptions ( UsageFlags . Output ) ;
114+ result . output = this . engine . mutate ( model , outputOptions ) as GraphQLModelMutation ;
115+ }
116+
117+ // Create input mutation if used as input
118+ if ( usage & UsageFlags . Input ) {
119+ const inputOptions = new GraphQLMutationOptions ( UsageFlags . Input ) ;
120+ result . input = this . engine . mutate ( model , inputOptions ) as GraphQLModelMutation ;
121+ }
122+
123+ return result ;
71124 }
72125
73126 /**
0 commit comments