Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2

defaults: &defaults
docker:
- image: joelfisch/stack-with-prebuilt-deps:latest
- image: joelfisch/stack-with-prebuilt-deps:v0.0.7
working_directory: ~/project

jobs:
Expand Down Expand Up @@ -64,6 +64,15 @@ jobs:
name: System tests level 2
command: ./.circleci/test_system_2

system2stripe:
<<: *defaults
steps:
- attach_workspace:
at: ~/project
- run:
name: System tests level 2 (Stripe)
command: ./.circleci/test_system_2_stripe

system3:
<<: *defaults
steps:
Expand Down Expand Up @@ -94,6 +103,9 @@ workflows:
- system2:
requires:
- build
- system2stripe:
requires:
- build
- system3:
requires:
- build
1 change: 0 additions & 1 deletion .circleci/test_system_2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
set -e

specifications=(
stripe-api.yml,stripe
official-petstore.yaml,official-petstore
petstore-running-example.yaml,petstore-running-example
)
Expand Down
51 changes: 51 additions & 0 deletions .circleci/test_system_2_stripe
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash

set -e

specifications=(
stripe-api.yml,stripe
)
outDir=openapi

[[ -d /root/.stack/snapshots/x86_64-linux/d2f1d79601122b1003c68e260f770c1d32d5fe7a028973b8192e738556d0b8b3 ]] && cp -Rn /root/.stack/snapshots/x86_64-linux/d2f1d79601122b1003c68e260f770c1d32d5fe7a028973b8192e738556d0b8b3 /root/.stack/snapshots/x86_64-linux/711b0e993dd52035c0641daec2c20681935ad613e80e3462008d52395107852b || true
GENERATOR_EXE=$(stack path --local-install-root)/bin/openapi3-code-generator-exe
cd .circleci/testing/level2

set +e
let errors=0

testingDir=$(pwd)

continueOnFailure () {
exitCode=$?
if [[ $exitCode -ne 0 ]]; then
let errors=errors+1
printf "\n\n=======================================\n"
echo "Exit code $exitCode received from step $1, skipping the following steps for specification file '$2'."
printf "=======================================\n\n"
continue
fi
}

for i in "${specifications[@]}"; do
cd $testingDir
IFS=","
set $i
specification=$1
cd $2
rm -rf $outDir level2-base
cp -R ../level2-base .
printf "\n\nRun package integration test for $specification\n"
echo "-------------------------"
if [[ $specification == "stripe-api.yml" ]]; then
$GENERATOR_EXE "../../../specifications/$specification" --output-dir=$outDir --force --property-type-suffix="'" --convert-to-camel-case
else
$GENERATOR_EXE "../../../specifications/$specification" --output-dir=$outDir --force
fi
continueOnFailure "code generation" "$specification"
stack test --fast
continueOnFailure "test" "$specification"
printf "\n-------------------------\n\n"
done

exit $errors
2 changes: 1 addition & 1 deletion nix/overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ in
(
self: super:
{
openapi3-code-generator = final.haskellPackages.callCabal2nix "openapi3-code-generator" (final.gitignoreSource ../openapi3-code-generator) { };
openapi3-code-generator = buildStrictly (final.haskellPackages.callCabal2nixWithOptions "openapi3-code-generator" (final.gitignoreSource ../openapi3-code-generator) "--no-hpack" { });
}
);
}
Expand Down
8 changes: 4 additions & 4 deletions nix/pkgs.nix
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
let
sources = import ./sources.nix;
pkgsv = import sources.nixpkgs;
niv-overlay = final: previous: { niv = (import sources.niv { }).niv; };
gitignore-src-overlay = final: previous: { inherit (import sources.gitignore { inherit (final) lib; }) gitignoreSource; };
ourPkgs =
pkgsv {
overlays =
[
niv-overlay
gitignore-src-overlay
(import (sources.autodocodec + "/nix/overlay.nix"))
(import (sources.safe-coloured-text + "/nix/overlay.nix"))
(final: previous: { niv = (import sources.niv { }).niv; })
(final: previous: { inherit (import sources.gitignore { inherit (final) lib; }) gitignoreSource; })
(import ./overlay.nix)
];
};
Expand Down
24 changes: 24 additions & 0 deletions nix/sources.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
{
"autodocodec": {
"branch": "master",
"description": "self(auto)- documenting encoders and decoders",
"homepage": "",
"owner": "NorfairKing",
"repo": "autodocodec",
"rev": "f0cb2ead0985b4394db0627e6befd7ce23c54c22",
"sha256": "1wyhwq38zl8ph2y1n8xjia67f7viyv253jg9rr3a78qnwlpvjxbd",
"type": "tarball",
"url": "https://github.com/NorfairKing/autodocodec/archive/f0cb2ead0985b4394db0627e6befd7ce23c54c22.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"gitignore": {
"branch": "master",
"description": "Nix function for filtering local git sources",
Expand Down Expand Up @@ -46,5 +58,17 @@
"type": "tarball",
"url": "https://github.com/cachix/pre-commit-hooks.nix/archive/40a51af82c1181b9dea3526c4124eee077e30213.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"safe-coloured-text": {
"branch": "master",
"description": null,
"homepage": "https://cs-syd.eu/posts/2021-03-07-safe-coloured-text",
"owner": "NorfairKing",
"repo": "safe-coloured-text",
"rev": "bd8700a555e977004e2dec24e12494a5a01ca500",
"sha256": "01frnv185r6mhqqkd6hqxd8p1h3yybf05xilyazxa07aqxhzn0an",
"type": "tarball",
"url": "https://github.com/NorfairKing/safe-coloured-text/archive/bd8700a555e977004e2dec24e12494a5a01ca500.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}
11 changes: 7 additions & 4 deletions openapi3-code-generator/openapi3-code-generator.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: cf1e3dff15e474ae5f844a8eda70a3bf67923dd895e3ad9097898bb122395653
-- hash: bb097229402f0cce133bf27168e3c33312434c994f68e4012532b4ccf84cf5da

name: openapi3-code-generator
version: 0.1.0.6
Expand Down Expand Up @@ -59,6 +59,8 @@ library
ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -Wpartial-fields -Widentities -Wcpp-undef
build-depends:
aeson
, autodocodec
, autodocodec-yaml
, base >=4.7 && <5
, bytestring
, containers
Expand All @@ -81,7 +83,6 @@ library
, unordered-containers
, vector
, yaml
, yamlparse-applicative
default-language: Haskell2010

executable openapi3-code-generator-exe
Expand All @@ -93,6 +94,8 @@ executable openapi3-code-generator-exe
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
build-depends:
aeson
, autodocodec
, autodocodec-yaml
, base >=4.7 && <5
, bytestring
, containers
Expand All @@ -116,7 +119,6 @@ executable openapi3-code-generator-exe
, unordered-containers
, vector
, yaml
, yamlparse-applicative
default-language: Haskell2010

test-suite openapi3-code-generator-test
Expand All @@ -137,6 +139,8 @@ test-suite openapi3-code-generator-test
build-depends:
QuickCheck
, aeson
, autodocodec
, autodocodec-yaml
, base >=4.7 && <5
, bytestring
, containers
Expand Down Expand Up @@ -166,5 +170,4 @@ test-suite openapi3-code-generator-test
, validity-text
, vector
, yaml
, yamlparse-applicative
default-language: Haskell2010
3 changes: 2 additions & 1 deletion openapi3-code-generator/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ dependencies:
- transformers
- time
- optparse-applicative
- yamlparse-applicative
- autodocodec
- autodocodec-yaml
- vector
- hashmap
- directory
Expand Down
15 changes: 4 additions & 11 deletions openapi3-code-generator/src/OpenAPI/Generate/Log.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@

module OpenAPI.Generate.Log where

import Control.Applicative
import Autodocodec
import Data.List (intersperse)
import Data.Text (Text)
import qualified Data.Text as T
import YamlParse.Applicative

-- | Data type representing the log severities
data LogSeverity
= TraceSeverity
| InfoSeverity
| WarningSeverity
| ErrorSeverity
deriving (Eq, Ord)
deriving (Eq, Ord, Bounded, Enum)

instance Show LogSeverity where
show ErrorSeverity = "ERROR"
Expand All @@ -30,14 +29,8 @@ instance Read LogSeverity where
readsPrec _ ('T' : 'R' : 'A' : 'C' : 'E' : rest) = [(TraceSeverity, rest)]
readsPrec _ _ = []

instance YamlSchema LogSeverity where
yamlSchema =
TraceSeverity <$ literalString (toText TraceSeverity)
<|> InfoSeverity <$ literalString (toText InfoSeverity)
<|> WarningSeverity <$ literalString (toText WarningSeverity)
<|> ErrorSeverity <$ literalString (toText ErrorSeverity)
where
toText = T.pack . show
instance HasCodec LogSeverity where
codec = shownBoundedEnumCodec

-- | A log entry containing the location within the OpenAPI specification where the message was produced, a severity and the actual message.
data LogEntry = LogEntry
Expand Down
5 changes: 3 additions & 2 deletions openapi3-code-generator/src/OpenAPI/Generate/OptParse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ module OpenAPI.Generate.OptParse
)
where

import Autodocodec.Yaml
import Control.Applicative
import Control.Monad
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified OpenAPI.Generate.Log as OAL
import OpenAPI.Generate.OptParse.Configuration
import OpenAPI.Generate.OptParse.Flags
Expand All @@ -23,7 +25,6 @@ import Options.Applicative.Help (string)
import Path.IO
import Path.Posix
import System.Exit
import YamlParse.Applicative as YamlParse

getSettings :: IO Settings
getSettings = do
Expand Down Expand Up @@ -170,5 +171,5 @@ flagsParser =
unlines
[ "Configuration file format:",
"",
T.unpack (YamlParse.prettyColourisedSchemaDoc @Configuration)
T.unpack $ TE.decodeUtf8 $ renderColouredSchemaViaCodec @Configuration
]
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE OverloadedStrings #-}

module OpenAPI.Generate.OptParse.Configuration
Expand All @@ -6,12 +7,13 @@ module OpenAPI.Generate.OptParse.Configuration
)
where

import Autodocodec
import Autodocodec.Yaml (readYamlConfigFile)
import Data.Aeson (FromJSON, ToJSON)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Yaml
import qualified OpenAPI.Generate.Log as OAL
import Path.IO
import YamlParse.Applicative as YamlParse

data Configuration = Configuration
{ configOpenApiSpecification :: !(Maybe Text),
Expand Down Expand Up @@ -45,45 +47,43 @@ data Configuration = Configuration
configOpaqueSchemas :: !(Maybe [Text]),
configWhiteListedSchemas :: !(Maybe [Text])
}
deriving (Show, Eq)
deriving stock (Show, Eq)
deriving (FromJSON, ToJSON) via (Autodocodec Configuration)

instance FromJSON Configuration where
parseJSON = viaYamlSchema

instance YamlSchema Configuration where
yamlSchema =
objectParser "Configuration" $
instance HasCodec Configuration where
codec =
object "Configuration" $
Configuration
<$> optionalField "specification" "The OpenAPI 3 specification file which code should be generated for."
<*> optionalField "outputDir" "The directory where the generated output is stored."
<*> optionalField "packageName" "Name of the stack project"
<*> optionalField "moduleName" "Name of the module"
<*> optionalField "logLevel" "Set the minium log level (e. g. WARN to only print warnings and errors). Possible values: TRACE, INFO, WARN, ERROR"
<*> optionalField "force" "Overwrite output directory without question"
<*> optionalField "incremental" "Only write new/changed files. Does not need --force flag to overwrite files."
<*> optionalField "dryRun" "Do not generate the output files but only print the generated code"
<*> optionalField "doNotGenerateStackProject" "Do not generate a stack project alongside the raw Haskell files"
<*> optionalField "generateNixFiles" "Generate Nix files alongside the raw Haskell files"
<*> optionalField "omitAdditionalOperationFunctions" "Omit the additional operation functions, which are: with explicit configuration and raw variants (returning the plain ByteString) for both with and without explicit configuration"
<*> optionalField "generateOptionalEmptyRequestBody" "Force the generator to create types for empty request bodies which are optional (e. g. no properties and required equals false)"
<*> optionalField "useNumberedVariantConstructors" "Use numbered data constructors (e. g. Variant1, Variant 2, etc.) for one-of types"
<*> optionalField "useFloatWithArbitraryPrecision" "Use Data.Scientific instead of Double to support arbitary number precision"
<*> optionalField "useIntWithArbitraryPrecision" "Use 'Integer' instead of 'Int' to support arbitrary number precision"
<*> optionalField "useDateTypesAsString" "Convert strings formatted as date / date-time to date types"
<*> optionalField "convertToCamelCase" "Convert names to CamelCase instead of using names which are as close as possible to the names provided in the specification"
<*> optionalField "propertyTypeSuffix" "Add a suffix to property types to prevent naming conflicts"
<*> optionalField "responseTypeSuffix" "The suffix which is added to the response data types"
<*> optionalField "responseBodyTypeSuffix" "The suffix which is added to the response body data types"
<*> optionalField "requestBodyTypeSuffix" "The suffix which is added to the request body data types"
<*> optionalField "arrayItemTypeSuffix" "The suffix which is added to the item type of an array. This is only applied to item types of top level array types which an alias is generated for."
<*> optionalField "parametersTypeSuffix" "The suffix which is added to the parameters type of operations"
<*> optionalField "parameterQueryPrefix" "The prefix which is added to query parameters"
<*> optionalField "parameterPathPrefix" "The prefix which is added to path parameters"
<*> optionalField "parameterCookiePrefix" "The prefix which is added to cookie parameters"
<*> optionalField "parameterHeaderPrefix" "The prefix which is added to header parameters"
<*> optionalField "operationsToGenerate" "If not all operations should be generated, this option can be used to specify all of them which should be generated. The value has to correspond to the value in the 'operationId' field in the OpenAPI 3 specification."
<*> optionalField "opaqueSchemas" "A list of schema names (exactly as they are named in the components.schemas section of the corresponding OpenAPI 3 specification) which are not further investigated while generating code from the specification. Only a type alias to 'Aeson.Value' is created for these schemas."
<*> optionalField "whiteListedSchemas" "A list of schema names (exactly as they are named in the components.schemas section of the corresponding OpenAPI 3 specification) which need to be generated. For all other schemas only a type alias to 'Aeson.Value' is created."
<$> optionalField "specification" "The OpenAPI 3 specification file which code should be generated for." .= configOpenApiSpecification
<*> optionalField "outputDir" "The directory where the generated output is stored." .= configOutputDir
<*> optionalField "packageName" "Name of the stack project" .= configPackageName
<*> optionalField "moduleName" "Name of the module" .= configModuleName
<*> optionalField "logLevel" "Set the minium log level (e. g. WARN to only print warnings and errors). Possible values: TRACE, INFO, WARN, ERROR" .= configLogLevel
<*> optionalField "force" "Overwrite output directory without question" .= configForce
<*> optionalField "incremental" "Only write new/changed files. Does not need --force flag to overwrite files." .= configIncremental
<*> optionalField "dryRun" "Do not generate the output files but only print the generated code" .= configDryRun
<*> optionalField "doNotGenerateStackProject" "Do not generate a stack project alongside the raw Haskell files" .= configDoNotGenerateStackProject
<*> optionalField "generateNixFiles" "Generate Nix files alongside the raw Haskell files" .= configGenerateNixFiles
<*> optionalField "omitAdditionalOperationFunctions" "Omit the additional operation functions, which are: with explicit configuration and raw variants (returning the plain ByteString) for both with and without explicit configuration" .= configOmitAdditionalOperationFunctions
<*> optionalField "generateOptionalEmptyRequestBody" "Force the generator to create types for empty request bodies which are optional (e. g. no properties and required equals false)" .= configGenerateOptionalEmptyRequestBody
<*> optionalField "useNumberedVariantConstructors" "Use numbered data constructors (e. g. Variant1, Variant 2, etc.) for one-of types" .= configUseNumberedVariantConstructors
<*> optionalField "useFloatWithArbitraryPrecision" "Use Data.Scientific instead of Double to support arbitary number precision" .= configUseFloatWithArbitraryPrecision
<*> optionalField "useIntWithArbitraryPrecision" "Use 'Integer' instead of 'Int' to support arbitrary number precision" .= configUseIntWithArbitraryPrecision
<*> optionalField "useDateTypesAsString" "Convert strings formatted as date / date-time to date types" .= configUseDateTypesAsString
<*> optionalField "convertToCamelCase" "Convert names to CamelCase instead of using names which are as close as possible to the names provided in the specification" .= configConvertToCamelCase
<*> optionalField "propertyTypeSuffix" "Add a suffix to property types to prevent naming conflicts" .= configPropertyTypeSuffix
<*> optionalField "responseTypeSuffix" "The suffix which is added to the response data types" .= configResponseTypeSuffix
<*> optionalField "responseBodyTypeSuffix" "The suffix which is added to the response body data types" .= configResponseBodyTypeSuffix
<*> optionalField "requestBodyTypeSuffix" "The suffix which is added to the request body data types" .= configRequestBodyTypeSuffix
<*> optionalField "arrayItemTypeSuffix" "The suffix which is added to the item type of an array. This is only applied to item types of top level array types which an alias is generated for." .= configArrayItemTypeSuffix
<*> optionalField "parametersTypeSuffix" "The suffix which is added to the parameters type of operations" .= configParametersTypeSuffix
<*> optionalField "parameterQueryPrefix" "The prefix which is added to query parameters" .= configParameterQueryPrefix
<*> optionalField "parameterPathPrefix" "The prefix which is added to path parameters" .= configParameterPathPrefix
<*> optionalField "parameterCookiePrefix" "The prefix which is added to cookie parameters" .= configParameterCookiePrefix
<*> optionalField "parameterHeaderPrefix" "The prefix which is added to header parameters" .= configParameterHeaderPrefix
<*> optionalField "operationsToGenerate" "If not all operations should be generated, this option can be used to specify all of them which should be generated. The value has to correspond to the value in the 'operationId' field in the OpenAPI 3 specification." .= configOperationsToGenerate
<*> optionalField "opaqueSchemas" "A list of schema names (exactly as they are named in the components.schemas section of the corresponding OpenAPI 3 specification) which are not further investigated while generating code from the specification. Only a type alias to 'Aeson.Value' is created for these schemas." .= configOpaqueSchemas
<*> optionalField "whiteListedSchemas" "A list of schema names (exactly as they are named in the components.schemas section of the corresponding OpenAPI 3 specification) which need to be generated. For all other schemas only a type alias to 'Aeson.Value' is created." .= configWhiteListedSchemas

getConfiguration :: Text -> IO (Maybe Configuration)
getConfiguration path = resolveFile' (T.unpack path) >>= YamlParse.readConfigFile
getConfiguration path = resolveFile' (T.unpack path) >>= readYamlConfigFile
Loading