Skip to content

Commit c3df31f

Browse files
raphaelclaude
andauthored
Name primitive alias types in OpenAPI 3.2 components (#3942)
The v3 schemafier inlines user types backed by primitives (such as named string enums) everywhere they are referenced. Inlining loses the design type name from the document and makes SDK generators emit one anonymous duplicated enum per reference site instead of a single named type. OpenAPI 3.2 documents now render primitive alias types as named component schemas referenced where used. The 3.0.3 documents are unchanged. Only the schemafier that feeds the document components names aliases: parameter and header schemafiers keep inlining since their schemas maps are discarded and references would dangle. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 8fa7b05 commit c3df31f

7 files changed

Lines changed: 413 additions & 1 deletion

File tree

http/codegen/openapi/v3/files_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ func TestFiles(t *testing.T) {
5858
{"endpoint", testdata.ExtensionDSL},
5959
{"endpoint-swagger", testdata.ExtensionSwaggerDSL},
6060
{"type-extension", testdata.TypeExtensionDSL},
61+
// Alias types stay inline in 3.0 documents (named in 3.2 only).
62+
{"alias-type", testdata.AliasTypeDSL},
6163
{"skip-response-body-encode-decode", testdata.SkipResponseBodyEncodeDecodeDSL},
6264
// TestValidations
6365
{"string", testdata.StringValidationDSL},
@@ -131,6 +133,7 @@ func TestFilesV32(t *testing.T) {
131133
{"sse-all-fields", testdata.SSEAllFieldsDSL},
132134
{"sse-mixed-results", testdata.MixedResultsDSL},
133135
{"websocket", testdata.StreamingResultDSL},
136+
{"alias-type", testdata.AliasTypeDSL},
134137
}
135138
for _, c := range cases {
136139
t.Run(c.Name, func(t *testing.T) {
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{
2+
"components": {
3+
"schemas": {
4+
"Setup": {
5+
"description": "Request body for testEndpoint.",
6+
"example": {
7+
"completed": [
8+
"where",
9+
"where",
10+
"where",
11+
"where"
12+
],
13+
"current": "where"
14+
},
15+
"properties": {
16+
"completed": {
17+
"example": [
18+
"where",
19+
"where"
20+
],
21+
"items": {
22+
"description": "Setup stage.",
23+
"enum": [
24+
"who",
25+
"when",
26+
"where",
27+
"what"
28+
],
29+
"example": "what",
30+
"type": "string"
31+
},
32+
"type": "array"
33+
},
34+
"current": {
35+
"description": "Setup stage.",
36+
"enum": [
37+
"who",
38+
"when",
39+
"where",
40+
"what"
41+
],
42+
"example": "who",
43+
"type": "string"
44+
}
45+
},
46+
"type": "object"
47+
}
48+
}
49+
},
50+
"info": {
51+
"title": "Goa API",
52+
"version": "0.0.1"
53+
},
54+
"openapi": "3.0.3",
55+
"paths": {
56+
"/": {
57+
"post": {
58+
"operationId": "testService#testEndpoint",
59+
"requestBody": {
60+
"content": {
61+
"application/json": {
62+
"example": {
63+
"completed": [
64+
"where",
65+
"where"
66+
],
67+
"current": "where"
68+
},
69+
"schema": {
70+
"$ref": "#/components/schemas/Setup"
71+
}
72+
}
73+
},
74+
"description": "Request body for testEndpoint.",
75+
"required": true
76+
},
77+
"responses": {
78+
"200": {
79+
"content": {
80+
"application/json": {
81+
"example": {
82+
"completed": [
83+
"when",
84+
"when",
85+
"when",
86+
"when"
87+
],
88+
"current": "when"
89+
},
90+
"schema": {
91+
"$ref": "#/components/schemas/Setup"
92+
}
93+
}
94+
},
95+
"description": "OK response."
96+
}
97+
},
98+
"summary": "testEndpoint testService",
99+
"tags": [
100+
"testService"
101+
]
102+
}
103+
}
104+
},
105+
"servers": [
106+
{
107+
"description": "Default server for test api",
108+
"url": "http://localhost:80"
109+
}
110+
],
111+
"tags": [
112+
{
113+
"name": "testService"
114+
}
115+
]
116+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
openapi: 3.0.3
2+
info:
3+
title: Goa API
4+
version: 0.0.1
5+
servers:
6+
- url: http://localhost:80
7+
description: Default server for test api
8+
paths:
9+
/:
10+
post:
11+
tags:
12+
- testService
13+
summary: testEndpoint testService
14+
operationId: testService#testEndpoint
15+
requestBody:
16+
description: Request body for testEndpoint.
17+
required: true
18+
content:
19+
application/json:
20+
schema:
21+
$ref: '#/components/schemas/Setup'
22+
example:
23+
completed:
24+
- where
25+
- where
26+
current: where
27+
responses:
28+
"200":
29+
description: OK response.
30+
content:
31+
application/json:
32+
schema:
33+
$ref: '#/components/schemas/Setup'
34+
example:
35+
completed:
36+
- when
37+
- when
38+
- when
39+
- when
40+
current: when
41+
components:
42+
schemas:
43+
Setup:
44+
type: object
45+
properties:
46+
completed:
47+
type: array
48+
items:
49+
type: string
50+
description: Setup stage.
51+
example: what
52+
enum:
53+
- who
54+
- when
55+
- where
56+
- what
57+
example:
58+
- where
59+
- where
60+
current:
61+
type: string
62+
description: Setup stage.
63+
example: who
64+
enum:
65+
- who
66+
- when
67+
- where
68+
- what
69+
description: Request body for testEndpoint.
70+
example:
71+
completed:
72+
- where
73+
- where
74+
- where
75+
- where
76+
current: where
77+
tags:
78+
- name: testService
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
{
2+
"components": {
3+
"schemas": {
4+
"Setup": {
5+
"description": "Request body for testEndpoint.",
6+
"example": {
7+
"completed": [
8+
"who",
9+
"who",
10+
"who",
11+
"who"
12+
],
13+
"current": "who"
14+
},
15+
"properties": {
16+
"completed": {
17+
"example": [
18+
"who",
19+
"who"
20+
],
21+
"items": {
22+
"$ref": "#/components/schemas/Stage"
23+
},
24+
"type": "array"
25+
},
26+
"current": {
27+
"$ref": "#/components/schemas/Stage"
28+
}
29+
},
30+
"type": "object"
31+
},
32+
"Stage": {
33+
"description": "Setup stage.",
34+
"enum": [
35+
"who",
36+
"when",
37+
"where",
38+
"what"
39+
],
40+
"example": "who",
41+
"type": "string"
42+
}
43+
}
44+
},
45+
"info": {
46+
"title": "Goa API",
47+
"version": "0.0.1"
48+
},
49+
"openapi": "3.2.0",
50+
"paths": {
51+
"/": {
52+
"post": {
53+
"operationId": "testService#testEndpoint",
54+
"requestBody": {
55+
"content": {
56+
"application/json": {
57+
"example": {
58+
"completed": [
59+
"who",
60+
"who",
61+
"who",
62+
"who"
63+
],
64+
"current": "who"
65+
},
66+
"schema": {
67+
"$ref": "#/components/schemas/Setup"
68+
}
69+
}
70+
},
71+
"description": "Request body for testEndpoint.",
72+
"required": true
73+
},
74+
"responses": {
75+
"200": {
76+
"content": {
77+
"application/json": {
78+
"example": {
79+
"completed": [
80+
"where",
81+
"where",
82+
"where"
83+
],
84+
"current": "where"
85+
},
86+
"schema": {
87+
"$ref": "#/components/schemas/Setup"
88+
}
89+
}
90+
},
91+
"description": "OK response."
92+
}
93+
},
94+
"summary": "testEndpoint testService",
95+
"tags": [
96+
"testService"
97+
]
98+
}
99+
}
100+
},
101+
"servers": [
102+
{
103+
"description": "Default server for test api",
104+
"name": "test api",
105+
"url": "http://localhost:80"
106+
}
107+
],
108+
"tags": [
109+
{
110+
"name": "testService"
111+
}
112+
]
113+
}

0 commit comments

Comments
 (0)