├── LICENSE ├── README.md ├── defaults.dhall ├── examples └── helloworld.dhall ├── types.dhall └── types ├── CallbackRef.dhall ├── Component.dhall ├── Contact.dhall ├── Documentation.dhall ├── Encoding.dhall ├── Example.dhall ├── ExampleRef.dhall ├── Header.dhall ├── HeaderRef.dhall ├── Info.dhall ├── License.dhall ├── LinkRef.dhall ├── MediaType.dhall ├── OpenAPI.dhall ├── Operation.dhall ├── ParamRef.dhall ├── Parameter.dhall ├── PathItem.dhall ├── Paths.dhall ├── Reference.dhall ├── ReqRef.dhall ├── Response.dhall ├── ResponseRef.dhall ├── Responses.dhall ├── SchemaRef.dhall ├── Security.dhall ├── Server.dhall └── Tag.dhall /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dhall-openapi 2 | 3 | Dhall expressions for OpenAPI 3.0.x 4 | 5 | ## Motivation 6 | 7 | Dhall is an excellent tool. I often think of it as "programmable schema". 8 | 9 | Not being able to go from Dhall to XSD and/or to Java/Haskell/Python, I wondered if I could at least go to an interim format such as OpenAPI so 10 | I can easily build a service and its domain objects in a less-verbose language that has a faster feedback loop that is _type-safe_. The result 11 | is this repo. 12 | 13 | ### Known Issues 14 | 15 | * The Schema type doesn't fairly represent the JSON schema structure as referenced in the OpenAPI Specification. This is a work in progress 16 | -------------------------------------------------------------------------------- /defaults.dhall: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } : ./types/OpenAPI.dhall 4 | -------------------------------------------------------------------------------- /examples/helloworld.dhall: -------------------------------------------------------------------------------- 1 | let Encoding = ../types/Encoding.dhall 2 | let Example = ../types/Example.dhall Text 3 | let Responses = ../types/Responses.dhall Text 4 | let ResponseRef = ../types/ResponseRef.dhall Text 5 | let Media = ../types/MediaType.dhall Text 6 | let SchemaRef = ../types/SchemaRef.dhall 7 | in 8 | { openapi = "3.0.2" 9 | , info = { title = "Example API", version = "3.0.2" } 10 | , servers = [{ url = "http://localhost/" }] 11 | , paths = [{ 12 | mapKey = "/hello" 13 | , mapValue = { 14 | get = { 15 | description = "Everything starts with hello world!" 16 | , responses = Responses.HttpStatus { 17 | mapKey = "200" 18 | , mapValue = ResponseRef.Resp { 19 | description = "A message." 20 | , headers = [] : List { mapKey : Text, mapValue : ../types/HeaderRef.dhall } 21 | , links = [] : List { mapKey : Text, mapValue : ../types/LinkRef.dhall } 22 | , content = [{ 23 | mapKey = "application/json" 24 | , mapValue = Media.Single { 25 | schema = (SchemaRef.Schema [ 26 | { mapKey = "type", mapValue = "string" } 27 | ]) 28 | , encoding = None Encoding 29 | , example = { summary = "Example output" 30 | , description = "Hello World example" 31 | , value = "Hello, world!" 32 | , externalValue = "" 33 | } 34 | } 35 | }] 36 | } 37 | } 38 | } 39 | } 40 | }] 41 | , components = [{=}] 42 | , security = [{=}] 43 | , tags = [] : List ../types/Tag.dhall 44 | , externalDocs = { url = "file://../README.md" } 45 | } 46 | -------------------------------------------------------------------------------- /types.dhall: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atcol/dhall-openapi/ced6a761762d924da0916284134778b37ab71b9f/types.dhall -------------------------------------------------------------------------------- /types/CallbackRef.dhall: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /types/Component.dhall: -------------------------------------------------------------------------------- 1 | { title : Text 2 | , description : Text 3 | , termsOfService : Text 4 | , contact : ./Contact.dhall 5 | , license : ./License.dhall 6 | , version : Text 7 | } 8 | -------------------------------------------------------------------------------- /types/Contact.dhall: -------------------------------------------------------------------------------- 1 | { name : Text 2 | , url : Text 3 | , email : Text 4 | } 5 | -------------------------------------------------------------------------------- /types/Documentation.dhall: -------------------------------------------------------------------------------- 1 | { description : Text 2 | , url : Text 3 | } 4 | -------------------------------------------------------------------------------- /types/Encoding.dhall: -------------------------------------------------------------------------------- 1 | { contentType : Text 2 | , headers : Text 3 | , style : List { mapKey : Text, mapValue : ./HeaderRef.dhall } 4 | , explode : Bool 5 | , allowReserved : Bool 6 | } 7 | -------------------------------------------------------------------------------- /types/Example.dhall: -------------------------------------------------------------------------------- 1 | let Example = \(a : Type) -> 2 | { summary : Text 3 | , description : Text 4 | , value : a 5 | , externalValue : Text 6 | } 7 | in Example 8 | -------------------------------------------------------------------------------- /types/ExampleRef.dhall: -------------------------------------------------------------------------------- 1 | < Example : ./Example.dhall | Ref : ./Reference.dhall > 2 | -------------------------------------------------------------------------------- /types/Header.dhall: -------------------------------------------------------------------------------- 1 | { description : Text 2 | , required : Bool 3 | , deprecated : Bool 4 | , allowEmptyValue : Bool 5 | } 6 | -------------------------------------------------------------------------------- /types/HeaderRef.dhall: -------------------------------------------------------------------------------- 1 | < Req : ./Header.dhall | Ref : ./Reference.dhall > 2 | -------------------------------------------------------------------------------- /types/Info.dhall: -------------------------------------------------------------------------------- 1 | { title : Text 2 | , description : Text 3 | , termsOfService : Text 4 | , contact : ./Contact.dhall 5 | , license : ./License.dhall 6 | , version : Text 7 | } 8 | -------------------------------------------------------------------------------- /types/License.dhall: -------------------------------------------------------------------------------- 1 | { name : Text 2 | , url : Text 3 | } 4 | -------------------------------------------------------------------------------- /types/LinkRef.dhall: -------------------------------------------------------------------------------- 1 | < Link : { operationRef : Text 2 | , operationId : Text 3 | , parameters : List { mapKey : Text, mapValue : {} } 4 | , requestBody : List { mapKey : Text, mapValue : {} } 5 | , description : Text 6 | , server : ./Server.dhall 7 | } 8 | | Ref : ./Reference.dhall 9 | > 10 | -------------------------------------------------------------------------------- /types/MediaType.dhall: -------------------------------------------------------------------------------- 1 | let Example = ./Example.dhall 2 | let MediaType = \(a : Type) -> 3 | < Single : { schema : ./SchemaRef.dhall 4 | , example : Example a 5 | , encoding : Optional ./Encoding.dhall 6 | } 7 | | Multiple : { schema : Optional ./SchemaRef.dhall 8 | , examples : (List { mapKey : Text, mapValue : (Example a) }) 9 | , encoding : Optional ./Encoding.dhall 10 | } 11 | > 12 | in MediaType 13 | -------------------------------------------------------------------------------- /types/OpenAPI.dhall: -------------------------------------------------------------------------------- 1 | { openapi : Text 2 | , info : ./Info.dhall 3 | , servers : List ./Server.dhall 4 | , paths : List ./Paths.dhall 5 | , components : List ./Component.dhall 6 | , security : List ./Security.dhall 7 | , tags : List ./Tag.dhall 8 | , externalDocs : ./Documentation.dhall 9 | } 10 | -------------------------------------------------------------------------------- /types/Operation.dhall: -------------------------------------------------------------------------------- 1 | { tags : List Text 2 | , summary : Text 3 | , description : Text 4 | , externalDocs : ./Documentation.dhall 5 | , operationId : Text 6 | , parameters : ./ParamRef.dhall 7 | , requestBody : ./ReqRef.dhall 8 | , responses : ./Responses.dhall 9 | , callbacks : List { mapKey : Text, mapValue: List ./CallbackRef.dhall } 10 | , deprecated : Bool 11 | , security : List ./Security.dhall 12 | , servers : List ./Server.dhall 13 | } 14 | -------------------------------------------------------------------------------- /types/ParamRef.dhall: -------------------------------------------------------------------------------- 1 | < Param : ./Parameter.dhall | Ref : ./Reference.dhall > 2 | -------------------------------------------------------------------------------- /types/Parameter.dhall: -------------------------------------------------------------------------------- 1 | { name : Text 2 | , `in` : Text 3 | , description : Text 4 | , required : Bool 5 | , deprecated : Bool 6 | , allowEmptyValue : Bool 7 | } 8 | -------------------------------------------------------------------------------- /types/PathItem.dhall: -------------------------------------------------------------------------------- 1 | { `$ref` : Text 2 | , summary : Text 3 | , description : Text 4 | , get : ./Operation.dhall 5 | , put : ./Operation.dhall 6 | , post : ./Operation.dhall 7 | , delete : ./Operation.dhall 8 | , options : ./Operation.dhall 9 | , head : ./Operation.dhall 10 | , patch : ./Operation.dhall 11 | , trace : ./Operation.dhall 12 | , servers : List ./Server.dhall 13 | , parameters : ./Parameter.dhall 14 | } 15 | -------------------------------------------------------------------------------- /types/Paths.dhall: -------------------------------------------------------------------------------- 1 | List { mapKey : Text, mapValue: /PathItem.dhall } 2 | -------------------------------------------------------------------------------- /types/Reference.dhall: -------------------------------------------------------------------------------- 1 | { `$ref` : Text 2 | } 3 | -------------------------------------------------------------------------------- /types/ReqRef.dhall: -------------------------------------------------------------------------------- 1 | let R = { description : Text, content : List { mapKey : Text, mapValue: List ./MediaType.dhall }, required : Bool } 2 | in 3 | < Req : R | Ref : ./Reference.dhall > 4 | -------------------------------------------------------------------------------- /types/Response.dhall: -------------------------------------------------------------------------------- 1 | \(a : Type) -> { description : Text 2 | , headers : List { mapKey : Text, mapValue : ./HeaderRef.dhall } 3 | , content : List { mapKey : Text, mapValue : ./MediaType.dhall a } 4 | , links : List { mapKey : Text, mapValue : ./LinkRef.dhall } 5 | } 6 | -------------------------------------------------------------------------------- /types/ResponseRef.dhall: -------------------------------------------------------------------------------- 1 | \(a : Type) -> < Resp : ./Response.dhall a 2 | | Ref : ./Reference.dhall > 3 | -------------------------------------------------------------------------------- /types/Responses.dhall: -------------------------------------------------------------------------------- 1 | \(a : Type) -> 2 | < Default : { default : ./ResponseRef.dhall a } 3 | | HttpStatus : { mapKey: Text, mapValue : ./ResponseRef.dhall a } 4 | > 5 | -------------------------------------------------------------------------------- /types/SchemaRef.dhall: -------------------------------------------------------------------------------- 1 | < Schema : List { mapKey : Text, mapValue : Text } | Ref : ./Reference.dhall > 2 | -------------------------------------------------------------------------------- /types/Security.dhall: -------------------------------------------------------------------------------- 1 | List { mapKey : Text, mapValue : List Text } 2 | -------------------------------------------------------------------------------- /types/Server.dhall: -------------------------------------------------------------------------------- 1 | let ServerVar = < Enum : { enum : List Text } | Default : { default : Text } | Description : { description : Text } > 2 | in 3 | { url : Text 4 | , description : Text 5 | , variables : List { mapKey : Text, mapValue : List { mapKey: Text, mapValue : List ServerVar } } 6 | } 7 | -------------------------------------------------------------------------------- /types/Tag.dhall: -------------------------------------------------------------------------------- 1 | List Text 2 | --------------------------------------------------------------------------------