Skip to content

Commit 722866d

Browse files
committed
Add elm-open-api-codegen example project
1 parent a0d64fb commit 722866d

File tree

12 files changed

+6052
-0
lines changed

12 files changed

+6052
-0
lines changed

example/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
codegen/Gen/CodeGen/Generate.elm

example/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# elm-open-api-codegen example
2+
3+
OpenAPI has built-in formats, such as `date-time`, but you can define your own
4+
custom ones, too--and with the `elm-open-api-codegen` package, you can control
5+
how data with your custom format is decoded, encoded, and transformed into URL
6+
params!
7+
8+
OpenAPI formats are specified by setting `format` alongside `type` in a spec.
9+
For example, this looks like:
10+
11+
```yaml
12+
components:
13+
schemas:
14+
ArticleId:
15+
type: string
16+
format: article-id
17+
```
18+
19+
To define a custom format, we use an Elm Pages script that calls the
20+
`elm-open-api-codegen` package to generate Elm code for an API schema, rather
21+
than using the `elm-open-api` CLI. This allows us to configure the code
22+
generator by using, for example, the `OpenApi.Config.withFormat` function.
23+
24+
This example includes an `ArticleId` module that defines an opaque id type for
25+
"articles" retrieved through a hypothetical API. We'd like the OpenAPI code
26+
generator to use our `ArticleId.decode` and `ArticleId.encode` functions when
27+
serializing Article IDs, so we need to define a custom format.
28+
29+
We have already run `elm-codegen install src/ArticleId.elm` in order to create
30+
the `codegen/Gen/ArticleId.elm` module. This is an `elm-codegen` helper module
31+
that makes it easier to generate code that uses the types and functions defined
32+
in `src/ArticleId.elm`. We use this helper module in our main script when
33+
telling the OpenAPI code generator what code should be generated for decoding
34+
and encoding our custom `article-id` OpenAPI format.
35+
36+
The Elm Pages script is
37+
[scripts/src/CodeGenOpenApi.elm](scripts/src/CodeGenOpenApi.elm).

example/codegen/Gen/ArticleId.elm

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
module Gen.ArticleId exposing
2+
( moduleName_, encode, decode, parse, toString, annotation_
3+
, call_, values_
4+
)
5+
6+
{-|
7+
# Generated bindings for ArticleId
8+
9+
@docs moduleName_, encode, decode, parse, toString, annotation_
10+
@docs call_, values_
11+
-}
12+
13+
14+
import Elm
15+
import Elm.Annotation as Type
16+
17+
18+
{-| The name of this module. -}
19+
moduleName_ : List String
20+
moduleName_ =
21+
[ "ArticleId" ]
22+
23+
24+
{-| encode: ArticleId.ArticleId -> Json.Encode.Value -}
25+
encode : Elm.Expression -> Elm.Expression
26+
encode encodeArg_ =
27+
Elm.apply
28+
(Elm.value
29+
{ importFrom = [ "ArticleId" ]
30+
, name = "encode"
31+
, annotation =
32+
Just
33+
(Type.function
34+
[ Type.namedWith [ "ArticleId" ] "ArticleId" [] ]
35+
(Type.namedWith [ "Json", "Encode" ] "Value" [])
36+
)
37+
}
38+
)
39+
[ encodeArg_ ]
40+
41+
42+
{-| decode: Json.Decode.Decoder ArticleId.ArticleId -}
43+
decode : Elm.Expression
44+
decode =
45+
Elm.value
46+
{ importFrom = [ "ArticleId" ]
47+
, name = "decode"
48+
, annotation =
49+
Just
50+
(Type.namedWith
51+
[ "Json", "Decode" ]
52+
"Decoder"
53+
[ Type.namedWith [ "ArticleId" ] "ArticleId" [] ]
54+
)
55+
}
56+
57+
58+
{-| parse: String -> Result.Result String ArticleId.ArticleId -}
59+
parse : String -> Elm.Expression
60+
parse parseArg_ =
61+
Elm.apply
62+
(Elm.value
63+
{ importFrom = [ "ArticleId" ]
64+
, name = "parse"
65+
, annotation =
66+
Just
67+
(Type.function
68+
[ Type.string ]
69+
(Type.namedWith
70+
[ "Result" ]
71+
"Result"
72+
[ Type.string
73+
, Type.namedWith [ "ArticleId" ] "ArticleId" []
74+
]
75+
)
76+
)
77+
}
78+
)
79+
[ Elm.string parseArg_ ]
80+
81+
82+
{-| toString: ArticleId.ArticleId -> String -}
83+
toString : Elm.Expression -> Elm.Expression
84+
toString toStringArg_ =
85+
Elm.apply
86+
(Elm.value
87+
{ importFrom = [ "ArticleId" ]
88+
, name = "toString"
89+
, annotation =
90+
Just
91+
(Type.function
92+
[ Type.namedWith [ "ArticleId" ] "ArticleId" [] ]
93+
Type.string
94+
)
95+
}
96+
)
97+
[ toStringArg_ ]
98+
99+
100+
annotation_ : { articleId : Type.Annotation }
101+
annotation_ =
102+
{ articleId = Type.namedWith [ "ArticleId" ] "ArticleId" [] }
103+
104+
105+
call_ :
106+
{ encode : Elm.Expression -> Elm.Expression
107+
, parse : Elm.Expression -> Elm.Expression
108+
, toString : Elm.Expression -> Elm.Expression
109+
}
110+
call_ =
111+
{ encode =
112+
\encodeArg_ ->
113+
Elm.apply
114+
(Elm.value
115+
{ importFrom = [ "ArticleId" ]
116+
, name = "encode"
117+
, annotation =
118+
Just
119+
(Type.function
120+
[ Type.namedWith
121+
[ "ArticleId" ]
122+
"ArticleId"
123+
[]
124+
]
125+
(Type.namedWith
126+
[ "Json", "Encode" ]
127+
"Value"
128+
[]
129+
)
130+
)
131+
}
132+
)
133+
[ encodeArg_ ]
134+
, parse =
135+
\parseArg_ ->
136+
Elm.apply
137+
(Elm.value
138+
{ importFrom = [ "ArticleId" ]
139+
, name = "parse"
140+
, annotation =
141+
Just
142+
(Type.function
143+
[ Type.string ]
144+
(Type.namedWith
145+
[ "Result" ]
146+
"Result"
147+
[ Type.string
148+
, Type.namedWith
149+
[ "ArticleId" ]
150+
"ArticleId"
151+
[]
152+
]
153+
)
154+
)
155+
}
156+
)
157+
[ parseArg_ ]
158+
, toString =
159+
\toStringArg_ ->
160+
Elm.apply
161+
(Elm.value
162+
{ importFrom = [ "ArticleId" ]
163+
, name = "toString"
164+
, annotation =
165+
Just
166+
(Type.function
167+
[ Type.namedWith
168+
[ "ArticleId" ]
169+
"ArticleId"
170+
[]
171+
]
172+
Type.string
173+
)
174+
}
175+
)
176+
[ toStringArg_ ]
177+
}
178+
179+
180+
values_ :
181+
{ encode : Elm.Expression
182+
, decode : Elm.Expression
183+
, parse : Elm.Expression
184+
, toString : Elm.Expression
185+
}
186+
values_ =
187+
{ encode =
188+
Elm.value
189+
{ importFrom = [ "ArticleId" ]
190+
, name = "encode"
191+
, annotation =
192+
Just
193+
(Type.function
194+
[ Type.namedWith [ "ArticleId" ] "ArticleId" [] ]
195+
(Type.namedWith [ "Json", "Encode" ] "Value" [])
196+
)
197+
}
198+
, decode =
199+
Elm.value
200+
{ importFrom = [ "ArticleId" ]
201+
, name = "decode"
202+
, annotation =
203+
Just
204+
(Type.namedWith
205+
[ "Json", "Decode" ]
206+
"Decoder"
207+
[ Type.namedWith [ "ArticleId" ] "ArticleId" [] ]
208+
)
209+
}
210+
, parse =
211+
Elm.value
212+
{ importFrom = [ "ArticleId" ]
213+
, name = "parse"
214+
, annotation =
215+
Just
216+
(Type.function
217+
[ Type.string ]
218+
(Type.namedWith
219+
[ "Result" ]
220+
"Result"
221+
[ Type.string
222+
, Type.namedWith [ "ArticleId" ] "ArticleId" []
223+
]
224+
)
225+
)
226+
}
227+
, toString =
228+
Elm.value
229+
{ importFrom = [ "ArticleId" ]
230+
, name = "toString"
231+
, annotation =
232+
Just
233+
(Type.function
234+
[ Type.namedWith [ "ArticleId" ] "ArticleId" [] ]
235+
Type.string
236+
)
237+
}
238+
}

example/codegen/elm.codegen.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"elm-codegen-version": "0.6.1",
3+
"codegen-helpers": {
4+
"packages": {},
5+
"local": [
6+
"src/ArticleId.elm"
7+
]
8+
}
9+
}

example/elm.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"type": "application",
3+
"source-directories": [
4+
"generated",
5+
"src"
6+
],
7+
"elm-version": "0.19.1",
8+
"dependencies": {
9+
"direct": {
10+
"elm/browser": "1.0.2",
11+
"elm/core": "1.0.5",
12+
"elm/html": "1.0.0"
13+
},
14+
"indirect": {
15+
"elm/json": "1.1.3",
16+
"elm/time": "1.0.0",
17+
"elm/url": "1.0.0",
18+
"elm/virtual-dom": "1.0.4"
19+
}
20+
},
21+
"test-dependencies": {
22+
"direct": {},
23+
"indirect": {}
24+
}
25+
}

example/openapi.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
openapi: 3.0.1
2+
info:
3+
title: "Example schema"
4+
version: "1"
5+
components:
6+
schemas:
7+
Article:
8+
description: Article
9+
type: object
10+
properties:
11+
id:
12+
type: string
13+
format: article-id
14+
content:
15+
type: string
16+
required:
17+
- id
18+
- content

0 commit comments

Comments
 (0)