1+ using Azure . Core . Pipeline ;
2+ using Flurl ;
13using System ;
24using System . Collections . Immutable ;
5+ using System . IO ;
36using System . Linq ;
7+ using System . Text . Json . Nodes ;
48using System . Text . Json . Serialization ;
9+ using System . Threading ;
10+ using System . Threading . Tasks ;
511
612namespace common ;
713
@@ -48,6 +54,10 @@ public record ApiCreateOrUpdateProperties
4854 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
4955 public string ? ApiRevisionDescription { get ; init ; }
5056
57+ [ JsonPropertyName ( "apiType" ) ]
58+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
59+ public string ? ApiType { get ; init ; }
60+
5161 [ JsonPropertyName ( "apiVersion" ) ]
5262 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
5363 public string ? ApiVersion { get ; init ; }
@@ -56,6 +66,10 @@ public record ApiCreateOrUpdateProperties
5666 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
5767 public string ? ApiVersionDescription { get ; init ; }
5868
69+ [ JsonPropertyName ( "apiVersionSet" ) ]
70+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
71+ public ApiVersionSetContractDetails ? ApiVersionSet { get ; init ; }
72+
5973 [ JsonPropertyName ( "apiVersionSetId" ) ]
6074 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
6175 public string ? ApiVersionSetId { get ; init ; }
@@ -72,22 +86,6 @@ public record ApiCreateOrUpdateProperties
7286 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
7387 public string ? Description { get ; init ; }
7488
75- [ JsonPropertyName ( "isCurrent" ) ]
76- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
77- public bool ? IsCurrent { get ; init ; }
78-
79- [ JsonPropertyName ( "license" ) ]
80- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
81- public ApiLicenseInformation ? License { get ; init ; }
82-
83- [ JsonPropertyName ( "apiType" ) ]
84- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
85- public string ? ApiType { get ; init ; }
86-
87- [ JsonPropertyName ( "apiVersionSet" ) ]
88- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
89- public ApiVersionSetContractDetails ? ApiVersionSet { get ; init ; }
90-
9189 [ JsonPropertyName ( "displayName" ) ]
9290 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
9391 public string ? DisplayName { get ; init ; }
@@ -96,6 +94,14 @@ public record ApiCreateOrUpdateProperties
9694 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
9795 public string ? Format { get ; init ; }
9896
97+ [ JsonPropertyName ( "isCurrent" ) ]
98+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
99+ public bool ? IsCurrent { get ; init ; }
100+
101+ [ JsonPropertyName ( "license" ) ]
102+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
103+ public ApiLicenseInformation ? License { get ; init ; }
104+
99105 [ JsonPropertyName ( "protocols" ) ]
100106 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
101107 public ImmutableArray < string > ? Protocols { get ; init ; }
@@ -110,18 +116,6 @@ public record ApiCreateOrUpdateProperties
110116 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
111117 public string ? SourceApiId { get ; init ; }
112118
113- [ JsonPropertyName ( "translateRequiredQueryParameters" ) ]
114- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
115- public string ? TranslateRequiredQueryParameters { get ; init ; }
116-
117- [ JsonPropertyName ( "value" ) ]
118- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
119- public string ? Value { get ; init ; }
120-
121- [ JsonPropertyName ( "wsdlSelector" ) ]
122- [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
123- public WsdlSelectorContract ? WsdlSelector { get ; init ; }
124-
125119 [ JsonPropertyName ( "subscriptionKeyParameterNames" ) ]
126120 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
127121 public SubscriptionKeyParameterNamesContract ? SubscriptionKeyParameterNames { get ; init ; }
@@ -136,10 +130,22 @@ public record ApiCreateOrUpdateProperties
136130 public string ? TermsOfServiceUrl { get ; init ; }
137131#pragma warning restore CA1056 // URI-like properties should not be strings
138132
133+ [ JsonPropertyName ( "translateRequiredQueryParameters" ) ]
134+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
135+ public string ? TranslateRequiredQueryParameters { get ; init ; }
136+
139137 [ JsonPropertyName ( "type" ) ]
140138 [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
141139 public string ? Type { get ; init ; }
142140
141+ [ JsonPropertyName ( "value" ) ]
142+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
143+ public string ? Value { get ; init ; }
144+
145+ [ JsonPropertyName ( "wsdlSelector" ) ]
146+ [ JsonIgnore ( Condition = JsonIgnoreCondition . WhenWritingDefault ) ]
147+ public WsdlSelectorContract ? WsdlSelector { get ; init ; }
148+
143149 public record AuthenticationSettingsContract
144150 {
145151 [ JsonPropertyName ( "oAuth2" ) ]
@@ -281,4 +287,87 @@ public static ResourceName Combine(ResourceName rootName, int revision) =>
281287 ? throw new InvalidOperationException ( $ "Revision must be positive.")
282288 : ResourceName . From ( $ "{ rootName } { separator } { revision } ")
283289 . IfErrorThrow ( ) ;
290+ }
291+
292+ public static partial class ResourceModule
293+ {
294+ private static async ValueTask PutApiInApim ( ResourceName name , JsonObject dto , GetResourceDtoFromApim getApimDto , HttpPipeline pipeline , ServiceUri serviceUri , CancellationToken cancellationToken )
295+ {
296+ IResourceWithDto resource = ApiResource . Instance ;
297+ ParentChain parentChain = ParentChain . Empty ;
298+
299+ var uri = resource . GetUri ( name , parentChain , serviceUri ) ;
300+ var formattedDto = await formatDto ( ) ;
301+ var result = await pipeline . PutJson ( uri , formattedDto , cancellationToken ) ;
302+ result . IfErrorThrow ( ) ;
303+
304+ // Non-current revisions are not allowed to update certain properties.
305+ // Replace them with the existing revision properties if necessary.
306+ async ValueTask < JsonObject > formatDto ( )
307+ {
308+ // If this is the current revision, return the DTO as-is.
309+ var rootName = ApiRevisionModule . GetRootName ( name ) ;
310+ if ( name == rootName )
311+ {
312+ return dto ;
313+ }
314+
315+ // Otherwise, update the DTO with the appropriate current revision properties.
316+ var existingDto = await getApimDto ( resource , rootName , parentChain , cancellationToken ) ;
317+
318+ var result = from existingDtoObject in JsonNodeModule . To < ApiDto > ( existingDto , resource . SerializerOptions )
319+ from newDtoObject in JsonNodeModule . To < ApiDto > ( dto , resource . SerializerOptions )
320+ let formattedDtoObject = newDtoObject with
321+ {
322+ Properties = newDtoObject . Properties with
323+ {
324+ Type = existingDtoObject . Properties . Type ,
325+ Description = existingDtoObject . Properties . Description ,
326+ SubscriptionRequired = existingDtoObject . Properties . SubscriptionRequired ,
327+ ApiVersion = existingDtoObject . Properties . ApiVersion ,
328+ ApiRevisionDescription = existingDtoObject . Properties . ApiRevisionDescription ,
329+ Path = existingDtoObject . Properties . Path ,
330+ Protocols = existingDtoObject . Properties . Protocols
331+ }
332+ }
333+ from updatedDto in JsonObjectModule . From ( formattedDtoObject , resource . SerializerOptions )
334+ select updatedDto ;
335+
336+ return result . IfErrorThrow ( ) ;
337+ }
338+ }
339+
340+ /// <summary>
341+ /// If the API type is not 'websocket' or 'graphql', remove the 'serviceUrl' property from the API information file DTO.
342+ /// </summary>
343+ private static JsonObject FormatInformationFileDto ( this ApiResource resource , JsonObject dtoJson )
344+ {
345+ var serializerOptions = ( ( IResourceWithDto ) resource ) . SerializerOptions ;
346+
347+ var dto = JsonNodeModule . To < ApiDto > ( dtoJson , serializerOptions )
348+ . IfErrorThrow ( ) ;
349+
350+ dto = new [ ] { "websocket" , "graphql" } . Contains ( dto . Properties . Type , StringComparer . OrdinalIgnoreCase )
351+ ? dto
352+ : dto with { Properties = dto . Properties with { ServiceUrl = null } } ;
353+
354+ return JsonObjectModule . From ( dto , serializerOptions )
355+ . IfErrorThrow ( ) ;
356+ }
357+
358+ private static Option < ( ResourceName Name , ParentChain Ancestors ) > ParseSpecificationFile ( this ApiResource resource , FileInfo ? file , ServiceDirectory serviceDirectory )
359+ {
360+ if ( file is null )
361+ {
362+ return Option . None ;
363+ }
364+
365+ var specificationFileNames = specifications . Select ( GetSpecificationFileName ) ;
366+ if ( specificationFileNames . Contains ( file . Name ) is false )
367+ {
368+ return Option . None ;
369+ }
370+
371+ return resource . ParseDirectory ( file . Directory , serviceDirectory ) ;
372+ }
284373}
0 commit comments