@@ -53,14 +53,12 @@ func MergeOpenAPISpecs(specs ...*openapi3.T) (*openapi3.T, error) {
5353if spec .Paths != nil {
5454for path , pathItem := range spec .Paths .Map () {
5555if existingPathItem , exists := merged .Paths .Map ()[path ]; exists {
56- mergedPathItem , err := mergePathItems (existingPathItem , pathItem )
56+ err := mergePathItems (existingPathItem , pathItem )
5757if err != nil {
5858return nil , fmt .Errorf ("error merging path %s from spec %d: %v" , path , i , err )
5959}
6060
61- merged .Paths .Set (path , mergedPathItem )
6261} else {
63-
6462merged .Paths .Set (path , pathItem )
6563}
6664}
@@ -89,89 +87,49 @@ func MergeOpenAPISpecs(specs ...*openapi3.T) (*openapi3.T, error) {
8987return merged , nil
9088}
9189
92- // mergePathItems merges two path items, combining their operations
93- func mergePathItems (existing , new * openapi3.PathItem ) (* openapi3.PathItem , error ) {
94- merged := & openapi3.PathItem {
95- Ref : existing .Ref ,
96- Summary : existing .Summary ,
97- Description : existing .Description ,
98- Servers : existing .Servers ,
99- Parameters : existing .Parameters ,
100- }
101-
102- // Copy existing operations
103- if existing .Get != nil {
104- merged .Get = existing .Get
105- }
106- if existing .Put != nil {
107- merged .Put = existing .Put
108- }
109- if existing .Post != nil {
110- merged .Post = existing .Post
111- }
112- if existing .Delete != nil {
113- merged .Delete = existing .Delete
114- }
115- if existing .Options != nil {
116- merged .Options = existing .Options
117- }
118- if existing .Head != nil {
119- merged .Head = existing .Head
120- }
121- if existing .Patch != nil {
122- merged .Patch = existing .Patch
123- }
124- if existing .Trace != nil {
125- merged .Trace = existing .Trace
126- }
127-
128- // Add new operations (overwrite existing operations with new ones)
90+ func mergePathItems (existing , new * openapi3.PathItem ) error {
91+ // TODO: error and log warn when new one overrides existing one
12992if new .Get != nil {
130- merged .Get = new .Get
93+ existing .Get = new .Get
13194}
13295if new .Put != nil {
133- merged .Put = new .Put
96+ existing .Put = new .Put
13497}
13598if new .Post != nil {
136- merged .Post = new .Post
99+ existing .Post = new .Post
137100}
138101if new .Delete != nil {
139- merged .Delete = new .Delete
102+ existing .Delete = new .Delete
140103}
141104if new .Options != nil {
142- merged .Options = new .Options
105+ existing .Options = new .Options
143106}
144107if new .Head != nil {
145- merged .Head = new .Head
108+ existing .Head = new .Head
146109}
147110if new .Patch != nil {
148- merged .Patch = new .Patch
111+ existing .Patch = new .Patch
149112}
150113if new .Trace != nil {
151- merged .Trace = new .Trace
114+ existing .Trace = new .Trace
152115}
153116
154- // Merge parameters
155117if new .Parameters != nil {
156- merged .Parameters = append ( merged .Parameters , new .Parameters ... )
118+ existing .Parameters = mergeParameters ( existing .Parameters , new .Parameters )
157119}
158120
159- // Merge servers
160121if new .Servers != nil {
161- merged .Servers = append (merged .Servers , new .Servers ... )
122+ existing .Servers = append (existing .Servers , new .Servers ... )
162123}
163124
164- return merged , nil
125+ return nil
165126}
166127
167- // mergeComponents merges components from source into target
168128func mergeComponents (target , source * openapi3.Components , specIndex int ) error {
169- // Merge schemas
170129if source .Schemas != nil {
171130maps .Copy (target .Schemas , source .Schemas )
172131}
173132
174- // Merge parameters
175133if source .Parameters != nil {
176134for name , param := range source .Parameters {
177135if _ , exists := target .Parameters [name ]; exists {
@@ -181,7 +139,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
181139}
182140}
183141
184- // Merge headers
185142if source .Headers != nil {
186143for name , header := range source .Headers {
187144if _ , exists := target .Headers [name ]; exists {
@@ -191,7 +148,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
191148}
192149}
193150
194- // Merge request bodies
195151if source .RequestBodies != nil {
196152for name , requestBody := range source .RequestBodies {
197153if _ , exists := target .RequestBodies [name ]; exists {
@@ -201,7 +157,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
201157}
202158}
203159
204- // Merge responses
205160if source .Responses != nil {
206161for name , response := range source .Responses {
207162if _ , exists := target .Responses [name ]; exists {
@@ -211,7 +166,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
211166}
212167}
213168
214- // Merge security schemes
215169if source .SecuritySchemes != nil {
216170for name , securityScheme := range source .SecuritySchemes {
217171if _ , exists := target .SecuritySchemes [name ]; exists {
@@ -221,7 +175,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
221175}
222176}
223177
224- // Merge examples
225178if source .Examples != nil {
226179for name , example := range source .Examples {
227180if _ , exists := target .Examples [name ]; exists {
@@ -231,7 +184,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
231184}
232185}
233186
234- // Merge links
235187if source .Links != nil {
236188for name , link := range source .Links {
237189if _ , exists := target .Links [name ]; exists {
@@ -241,7 +193,6 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
241193}
242194}
243195
244- // Merge callbacks
245196if source .Callbacks != nil {
246197for name , callback := range source .Callbacks {
247198if _ , exists := target .Callbacks [name ]; exists {
@@ -253,3 +204,48 @@ func mergeComponents(target, source *openapi3.Components, specIndex int) error {
253204
254205return nil
255206}
207+
208+ func mergeParameters (existing , new openapi3.Parameters ) openapi3.Parameters {
209+ if len (existing ) == 0 {
210+ return new
211+ }
212+ if len (new ) == 0 {
213+ return existing
214+ }
215+
216+ paramMap := make (map [string ]* openapi3.ParameterRef )
217+ var result openapi3.Parameters
218+
219+ for _ , param := range existing {
220+ if param != nil && param .Value != nil {
221+ key := getParameterKey (param .Value )
222+ paramMap [key ] = param
223+ result = append (result , param )
224+ }
225+ }
226+
227+ for _ , param := range new {
228+ if param != nil && param .Value != nil {
229+ key := getParameterKey (param .Value )
230+ if existingParam , exists := paramMap [key ]; exists {
231+ for i , resultParam := range result {
232+ if resultParam == existingParam {
233+ result [i ] = param
234+ break
235+ }
236+ }
237+ paramMap [key ] = param
238+ } else {
239+ // Add new parameter
240+ paramMap [key ] = param
241+ result = append (result , param )
242+ }
243+ }
244+ }
245+
246+ return result
247+ }
248+
249+ func getParameterKey (param * openapi3.Parameter ) string {
250+ return param .Name + ":" + param .In
251+ }
0 commit comments