[elm] Add support for Elm 0.19 (#937)

* [elm] Add support for Elm 0.19

* add elm 0.18 samples, update cli option

* fix elm 0.18 compile test

* [elm] 0.19 fixes & improvements
This commit is contained in:
Erik Timmers 2018-09-04 08:24:43 +02:00 committed by William Cheng
parent 9b38618f68
commit b24b6df448
57 changed files with 1398 additions and 110 deletions

32
bin/elm-0.18-petstore.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/sh
SCRIPT="$0"
echo "# START SCRIPT: $SCRIPT"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
if [ ! -f "$executable" ]
then
mvn -B clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g elm -t modules/openapi-generator/src/main/resources/elm -o samples/client/petstore/elm-0.18 --additional-properties elmVersion=0.18 $@"
java $JAVA_OPTS -jar $executable $ags

View File

@ -22,6 +22,7 @@ import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.NumberSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.responses.ApiResponse;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
@ -49,16 +50,19 @@ import java.util.TreeSet;
public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final String X_ENCODER = "x-encoder";
private static final String X_DECODER = "x-decoder";
private static final String ELM_VERSION = "elmVersion";
private static final String ENCODER = "elmEncoder";
private static final String DECODER = "elmDecoder";
private static final String X_DISCRIMINATOR_TYPE = "x-discriminator-value";
private static final String X_UNION_TYPE = "x-union-type";
private static final String UNION_TYPE = "elmUnionType";
private Set<String> customPrimitives = new HashSet<String>();
protected String packageName = "openapi";
protected String packageVersion = "1.0.0";
private ElmVersion elmVersion = ElmVersion.ELM_019;
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@ -144,13 +148,52 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.clear();
final CliOption elmVersion = new CliOption(ELM_VERSION, "Elm version: 0.18, 0.19").defaultValue("0.19");
final Map<String, String> supportedVersions = new HashMap<>();
supportedVersions.put("0.18", "Elm 0.18");
supportedVersions.put("0.19", "Elm 0.19");
elmVersion.setEnum(supportedVersions);
cliOptions.add(elmVersion);
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(ELM_VERSION)) {
final String version = (String) additionalProperties.get(ELM_VERSION);
if ("0.18".equals(version)) {
elmVersion = ElmVersion.ELM_018;
}
}
switch (elmVersion) {
case ELM_018:
additionalProperties.put("isElm018", true);
break;
case ELM_019:
additionalProperties.put("isElm019", true);
break;
default:
throw new RuntimeException("Undefined Elm version");
}
supportingFiles.add(new SupportingFile("Byte.mustache", "src", "Byte.elm"));
supportingFiles.add(new SupportingFile("DateOnly.mustache", "src", "DateOnly.elm"));
supportingFiles.add(new SupportingFile("DateTime.mustache", "src", "DateTime.elm"));
supportingFiles.add(new SupportingFile("Main.mustache", "src", "Main.elm"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("elm-package.mustache", "", "elm-package.json"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
if (ElmVersion.ELM_018.equals(elmVersion)) {
supportingFiles.add(new SupportingFile("DateOnly018.mustache", "src", "DateOnly.elm"));
supportingFiles.add(new SupportingFile("DateTime018.mustache", "src", "DateTime.elm"));
supportingFiles.add(new SupportingFile("elm-package.mustache", "", "elm-package.json"));
supportingFiles.add(new SupportingFile("Main018.mustache", "src", "Main.elm"));
}
if (ElmVersion.ELM_019.equals(elmVersion)) {
supportingFiles.add(new SupportingFile("DateOnly019.mustache", "src", "DateOnly.elm"));
supportingFiles.add(new SupportingFile("DateTime019.mustache", "src", "DateTime.elm"));
supportingFiles.add(new SupportingFile("elm.mustache", "", "elm.json"));
supportingFiles.add(new SupportingFile("Main019.mustache", "src", "Main.elm"));
}
}
@Override
@ -279,7 +322,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
CodegenModel cm = (CodegenModel) mo.get("model");
if (cm.isEnum) {
this.addEncoderAndDecoder(cm.vendorExtensions, cm.classname, false, false);
cm.vendorExtensions.put(X_UNION_TYPE, cm.classname);
cm.vendorExtensions.put(UNION_TYPE, cm.classname);
} else if (cm.isAlias) {
this.addEncoderAndDecoder(cm.vendorExtensions, cm.dataType, false, true);
}
@ -365,11 +408,11 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
elmImport.moduleName = modulePrefix + property.complexType;
elmImport.exposures = new TreeSet<>();
elmImport.exposures.add(property.complexType);
if (property.vendorExtensions.containsKey(X_DECODER)) {
elmImport.exposures.add((String) property.vendorExtensions.get(X_DECODER));
if (property.vendorExtensions.containsKey(DECODER)) {
elmImport.exposures.add((String) property.vendorExtensions.get(DECODER));
}
if (property.vendorExtensions.containsKey(X_ENCODER)) {
elmImport.exposures.add((String) property.vendorExtensions.get(X_ENCODER));
if (property.vendorExtensions.containsKey(ENCODER)) {
elmImport.exposures.add((String) property.vendorExtensions.get(ENCODER));
}
elmImport.hasExposures = true;
return elmImport;
@ -391,13 +434,13 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
for (CodegenOperation op : ops) {
String path = op.path;
for (CodegenParameter param : op.pathParams) {
final String var = param.isString ? param.paramName : "toString " + param.paramName;
final String var = paramToString(param);
path = path.replace("{" + param.paramName + "}", "\" ++ " + var + " ++ \"");
}
op.path = ("\"" + path + "\"").replaceAll(" \\+\\+ \"\"", "");
if (op.bodyParam != null && !op.bodyParam.isPrimitiveType && !op.bodyParam.isMapContainer) {
final String encoder = (String) op.bodyParam.vendorExtensions.get(X_ENCODER);
final String encoder = (String) op.bodyParam.vendorExtensions.get(ENCODER);
if (encoder != null) {
if (!dependencies.containsKey(op.bodyParam.dataType)) {
dependencies.put(op.bodyParam.dataType, new TreeSet<String>());
@ -409,7 +452,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
if (resp.primitiveType || resp.isMapContainer) {
continue;
}
final String decoder = (String) resp.vendorExtensions.get(X_DECODER);
final String decoder = (String) resp.vendorExtensions.get(DECODER);
if (decoder != null) {
if (!dependencies.containsKey(resp.dataType)) {
dependencies.put(resp.dataType, new TreeSet<String>());
@ -473,6 +516,23 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
return "(Just " + value + ")";
}
private String paramToString(final CodegenParameter param) {
final String paramName = param.paramName;
if (param.isString) {
return paramName;
}
if (ElmVersion.ELM_018.equals(elmVersion)) {
return "toString " + paramName;
}
if (param.isInteger || param.isLong) {
return "String.fromInt " + paramName;
}
if (param.isFloat || param.isDouble) {
return "String.fromFloat " + paramName;
}
throw new RuntimeException("Parameter '" + paramName + "' cannot be converted to a string");
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
@ -507,7 +567,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
final String dataType = property.isEnum ? property.baseName : property.dataType;
addEncoderAndDecoder(property.vendorExtensions, dataType, property.isMapContainer, property.isPrimitiveType && !property.isEnum);
if (property.isEnum) {
property.vendorExtensions.put(X_UNION_TYPE, property.datatypeWithEnum);
property.vendorExtensions.put(UNION_TYPE, property.datatypeWithEnum);
}
return property;
@ -545,11 +605,11 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
encoderName = baseName + "Encoder";
decoderName = baseName + "Decoder";
}
if (!vendorExtensions.containsKey(X_ENCODER)) {
vendorExtensions.put(X_ENCODER, encoderName);
if (!vendorExtensions.containsKey(ENCODER)) {
vendorExtensions.put(ENCODER, encoderName);
}
if (!vendorExtensions.containsKey(X_DECODER)) {
vendorExtensions.put(X_DECODER, decoderName);
if (!vendorExtensions.containsKey(DECODER)) {
vendorExtensions.put(DECODER, decoderName);
}
}
@ -559,4 +619,9 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
public Set<String> exposures;
public Boolean hasExposures;
}
private enum ElmVersion {
ELM_018,
ELM_019
}
}

View File

@ -16,4 +16,3 @@ byteDecoder =
byteEncoder : Byte -> Encode.Value
byteEncoder model =
Encode.string model

View File

@ -0,0 +1,34 @@
module DateOnly exposing (DateOnly, dateOnlyDecoder, dateOnlyEncoder)
import Iso8601
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result
import Time
type alias DateOnly =
Time.Posix
dateOnlyDecoder : Decoder DateOnly
dateOnlyDecoder =
Decode.string
|> Decode.andThen decodeIsoString
dateOnlyEncoder : DateOnly -> Encode.Value
dateOnlyEncoder model =
Iso8601.fromTime model
|> String.left 10
|> Encode.string
decodeIsoString : String -> Decoder DateOnly
decodeIsoString str =
case Iso8601.toTime (str ++ "T00:00:00.000Z") of
Result.Ok posix ->
Decode.succeed posix
Result.Err _ ->
Decode.fail <| "Invalid date: " ++ str

View File

@ -0,0 +1,32 @@
module DateTime exposing (DateTime, dateTimeDecoder, dateTimeEncoder)
import Iso8601
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result
import Time
type alias DateTime =
Time.Posix
dateTimeDecoder : Decoder DateTime
dateTimeDecoder =
Decode.string
|> Decode.andThen decodeIsoString
dateTimeEncoder : DateTime -> Encode.Value
dateTimeEncoder model =
Encode.string <| Iso8601.fromTime model
decodeIsoString : String -> Decoder DateTime
decodeIsoString str =
case Iso8601.toTime str of
Result.Ok posix ->
Decode.succeed posix
Result.Err _ ->
Decode.fail <| "Invalid date: " ++ str

View File

@ -1,9 +1,6 @@
module Main exposing (..)
module Main exposing (main)
import Json.Decode as Decode
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import Http
import Html exposing (Html)
main : Program Never Model Msg
@ -15,29 +12,49 @@ main =
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ status : Maybe Int
{ value : Int
}
init : (Model, Cmd Msg)
init : ( Model, Cmd Msg )
init =
( Model Nothing, Cmd.none )
( Model 0, Cmd.none )
-- UPDATE
type Msg
= NoOp
update : Msg -> Model -> (Model, Cmd Msg)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
NoOp ->
( model, Cmd.none )
view : Model -> Html Msg
view model =
Html.text "main"
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Html Msg
view _ =
Html.text "main"

View File

@ -0,0 +1,61 @@
module Main exposing (main)
import Browser
import Html exposing (Html)
main : Program () Model Msg
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ value : Int
}
init : () -> ( Model, Cmd Msg )
init _ =
( Model 0, Cmd.none )
-- UPDATE
type Msg
= NoOp
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
NoOp ->
( model, Cmd.none )
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Html Msg
view _ =
Html.text "main"

View File

@ -1,7 +1,7 @@
{{classVarName}}Decoder : Decoder {{classname}}
{{classVarName}}Decoder =
decode {{classname}}
{{#isElm018}}decode{{/isElm018}}{{#isElm019}}Decode.succeed{{/isElm019}} {{classname}}
{{#allVars}}
{{^discriminatorValue}} |> {{>fieldDecoder}}
{{/discriminatorValue}}
{{/allVars}}
{{/allVars}}

View File

@ -23,8 +23,8 @@ basePath =
{ method = "{{httpMethod}}"
, url = basePath ++ {{{path}}}
, headers = []
, body = {{#bodyParam}}Http.jsonBody <| {{vendorExtensions.x-encoder}} model{{/bodyParam}}{{^bodyParam}}Http.emptyBody{{/bodyParam}}
, expect = {{^responses}}Http.expectStringResponse (\_ -> Ok ()){{/responses}}{{#responses}}{{#-first}}{{^dataType}}Http.expectStringResponse (\_ -> Ok ()){{/dataType}}{{#dataType}}Http.expectJson {{#isMapContainer}}(Decode.dict {{/isMapContainer}}{{#isListContainer}}(Decode.list {{/isListContainer}}{{#vendorExtensions}}{{x-decoder}}{{/vendorExtensions}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/dataType}}{{/-first}}{{/responses}}
, body = {{#bodyParam}}Http.jsonBody <| {{vendorExtensions.elmEncoder}} model{{/bodyParam}}{{^bodyParam}}Http.emptyBody{{/bodyParam}}
, expect = {{^responses}}Http.expectStringResponse (\_ -> Ok ()){{/responses}}{{#responses}}{{#-first}}{{^dataType}}Http.expectStringResponse (\_ -> Ok ()){{/dataType}}{{#dataType}}Http.expectJson {{#isMapContainer}}(Decode.dict {{/isMapContainer}}{{#isListContainer}}(Decode.list {{/isListContainer}}{{#vendorExtensions}}{{elmDecoder}}{{/vendorExtensions}}{{#isListContainer}}){{/isListContainer}}{{#isMapContainer}}){{/isMapContainer}}{{/dataType}}{{/-first}}{{/responses}}
, timeout = Just 30000
, withCredentials = False
}

View File

@ -0,0 +1,28 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.0",
"dependencies": {
"direct": {
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
"elm/browser": "1.0.0",
"elm/core": "1.0.0",
"elm/html": "1.0.0",
"elm/http": "1.0.0",
"elm/json": "1.0.0",
"elm/time": "1.0.0",
"rtfeldman/elm-iso8601-date-strings": "1.0.0"
},
"indirect": {
"elm/parser": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.0"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}

View File

@ -1 +1 @@
{{#required}}required{{/required}}{{^required}}optional{{/required}} "{{baseName}}" {{^required}}(Decode.nullable {{/required}}{{#isContainer}}(Decode.list {{/isContainer}}{{vendorExtensions.x-decoder}}{{#isContainer}}){{/isContainer}}{{^required}}){{/required}}{{^required}} {{{defaultValue}}}{{/required}}
{{#required}}required{{/required}}{{^required}}optional{{/required}} "{{baseName}}" {{^required}}(Decode.nullable {{/required}}{{#isContainer}}(Decode.list {{/isContainer}}{{vendorExtensions.elmDecoder}}{{#isContainer}}){{/isContainer}}{{^required}}){{/required}}{{^required}} {{{defaultValue}}}{{/required}}

View File

@ -1 +1 @@
( "{{baseName}}", {{#discriminatorValue}}Encode.string "{{discriminatorValue}}"{{/discriminatorValue}}{{^discriminatorValue}}{{^required}}withDefault Encode.null (map {{/required}}{{#isContainer}}(Encode.list << List.map {{/isContainer}}{{vendorExtensions.x-encoder}}{{#isContainer}}){{/isContainer}} model.{{name}}{{^required}}){{/required}}{{/discriminatorValue}} )
( "{{baseName}}", {{#discriminatorValue}}Encode.string "{{discriminatorValue}}"{{/discriminatorValue}}{{^discriminatorValue}}{{^required}}withDefault Encode.null (map {{/required}}{{#isContainer}}(Encode.list {{#isElm018}}<< List.map {{/isElm018}}{{/isContainer}}{{vendorExtensions.elmEncoder}}{{#isContainer}}){{/isContainer}} model.{{name}}{{^required}}){{/required}}{{/discriminatorValue}} )

View File

@ -1,9 +1,9 @@
{{>licenseInfo}}
module Data.{{classname}} exposing ({{#models}}{{#model}}{{classname}}{{#hasChildren}}(..){{/hasChildren}}{{#isEnum}}(..){{/isEnum}}{{^isEnum}}{{#vars}}{{#isEnum}}, {{vendorExtensions.x-union-type}}(..){{/isEnum}}{{/vars}}{{/isEnum}}, {{classVarName}}Decoder, {{classVarName}}Encoder{{/model}}{{/models}})
module Data.{{classname}} exposing ({{#models}}{{#model}}{{classname}}{{#hasChildren}}(..){{/hasChildren}}{{#isEnum}}(..){{/isEnum}}{{^isEnum}}{{#vars}}{{#isEnum}}, {{vendorExtensions.elmUnionType}}(..){{/isEnum}}{{/vars}}{{/isEnum}}, {{classVarName}}Decoder, {{classVarName}}Encoder{{/model}}{{/models}})
{{>imports}}import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing ({{#isElm018}}decode, {{/isElm018}}optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{{#models}}

View File

@ -4,9 +4,9 @@ type alias {{classname}} =
{{classVarName}}Decoder : Decoder {{classname}}
{{classVarName}}Decoder =
Decode.list {{vendorExtensions.x-decoder}}
Decode.list {{vendorExtensions.elmDecoder}}
{{classVarName}}Encoder : {{classname}} -> Encode.Value
{{classVarName}}Encoder model =
Encode.list (List.map {{vendorExtensions.x-encoder}} model)
{{classVarName}}Encoder items =
Encode.list {{#isElm018}}(List.map {{/isElm018}}{{vendorExtensions.elmEncoder}} items{{#isElm018}}){{/isElm018}}

View File

@ -21,7 +21,7 @@ type {{classname}}
_ ->
Decode.fail <|
"Trying to decode {{classname}}, but {{{discriminatorName}}} "
++ toString {{{discriminatorName}}} ++ " is not supported."
++ {{{discriminatorName}}} ++ " is not supported."
{{classVarName}}Encoder : {{classname}} -> Encode.Value

View File

@ -4,9 +4,9 @@ type alias {{classname}}
{{classVarName}}Decoder : Decoder {{classname}}
{{classVarName}}Decoder =
{{vendorExtensions.x-decoder}}
{{vendorExtensions.elmDecoder}}
{{classVarName}}Encoder : {{classname}} -> Encode.Value
{{classVarName}}Encoder =
{{vendorExtensions.x-encoder}}
{{vendorExtensions.elmEncoder}}

View File

@ -1,4 +1,4 @@
type {{#vendorExtensions}}{{x-union-type}}{{/vendorExtensions}}
type {{#vendorExtensions}}{{elmUnionType}}{{/vendorExtensions}}
{{#allowableValues}}
{{#enumVars}}
{{#-first}}={{/-first}}{{^-first}}|{{/-first}} {{name}}

View File

@ -1,5 +1,5 @@
{{vendorExtensions.x-decoder}} : Decoder {{vendorExtensions.x-union-type}}
{{vendorExtensions.x-decoder}} =
{{vendorExtensions.elmDecoder}} : Decoder {{vendorExtensions.elmUnionType}}
{{vendorExtensions.elmDecoder}} =
Decode.string
|> Decode.andThen (\str ->
case str of

View File

@ -1,5 +1,5 @@
{{vendorExtensions.x-encoder}} : {{vendorExtensions.x-union-type}} -> Encode.Value
{{vendorExtensions.x-encoder}} model =
{{vendorExtensions.elmEncoder}} : {{vendorExtensions.elmUnionType}} -> Encode.Value
{{vendorExtensions.elmEncoder}} model =
case model of
{{#allowableValues}}
{{#enumVars}}

View File

@ -1007,7 +1007,7 @@
<!-- clients -->
<module>samples/client/petstore/dart2/petstore</module>
<module>samples/client/petstore/haskell-http-client</module>
<module>samples/client/petstore/elm</module>
<module>samples/client/petstore/elm-0.18</module>
<module>samples/client/petstore/groovy</module>
<module>samples/client/petstore/rust</module>
<!--<module>samples/client/petstore/perl</module>-->
@ -1049,6 +1049,7 @@
</activation>
<modules>
<!-- clients -->
<module>samples/client/petstore/elm</module>
<module>samples/client/petstore/elixir</module>
<module>samples/client/petstore/erlang-client</module>
<!-- servers -->

View File

@ -0,0 +1 @@
/elm-stuff

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1 @@
3.2.3-SNAPSHOT

View File

@ -0,0 +1,10 @@
# Elm API client
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
## Overview
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client.
- API version: 1.0.0
- Package version:
- Build package: org.openapitools.codegen.languages.ElmClientCodegen

View File

@ -0,0 +1,14 @@
#!/bin/bash -e
# elm 0.18 make all elm files under src
for ELM in `find src -name "*.elm"`
do
echo "Compiling $ELM"
elm make $ELM --output /dev/null --yes
rc=$?
if [[ $rc != 0 ]]
then
echo "ERROR!! FAILED TO COMPILE $ELM"
exit $rc;
fi
done

View File

@ -0,0 +1,43 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>Elm018ClientTests</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Elm 0.18 Petstore Client</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>bundle-test</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>./elm-0.18-compile-test</executable>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,18 @@
module Byte exposing (Byte, byteDecoder, byteEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
type alias Byte =
String
byteDecoder : Decoder Byte
byteDecoder =
Decode.string
byteEncoder : Byte -> Encode.Value
byteEncoder model =
Encode.string model

View File

@ -0,0 +1,46 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Data.ApiResponse exposing (ApiResponse, apiResponseDecoder, apiResponseEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{-| Describes the result of uploading an image resource
-}
type alias ApiResponse =
{ code : Maybe Int
, type_ : Maybe String
, message : Maybe String
}
apiResponseDecoder : Decoder ApiResponse
apiResponseDecoder =
decode ApiResponse
|> optional "code" (Decode.nullable Decode.int) Nothing
|> optional "type" (Decode.nullable Decode.string) Nothing
|> optional "message" (Decode.nullable Decode.string) Nothing
apiResponseEncoder : ApiResponse -> Encode.Value
apiResponseEncoder model =
Encode.object
[ ( "code", withDefault Encode.null (map Encode.int model.code) )
, ( "type", withDefault Encode.null (map Encode.string model.type_) )
, ( "message", withDefault Encode.null (map Encode.string model.message) )
]

View File

@ -0,0 +1,43 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Data.Category exposing (Category, categoryDecoder, categoryEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{-| A category for a pet
-}
type alias Category =
{ id : Maybe Int
, name : Maybe String
}
categoryDecoder : Decoder Category
categoryDecoder =
decode Category
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "name" (Decode.nullable Decode.string) Nothing
categoryEncoder : Category -> Encode.Value
categoryEncoder model =
Encode.object
[ ( "id", withDefault Encode.null (map Encode.int model.id) )
, ( "name", withDefault Encode.null (map Encode.string model.name) )
]

View File

@ -0,0 +1,97 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Data.Order_ exposing (Order_, Status(..), orderDecoder, orderEncoder)
import DateTime exposing (DateTime, dateTimeDecoder, dateTimeEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{-| An order for a pets from the pet store
-}
type alias Order_ =
{ id : Maybe Int
, petId : Maybe Int
, quantity : Maybe Int
, shipDate : Maybe DateTime
, status : Maybe Status
, complete : Maybe Bool
}
type Status
= Placed
| Approved
| Delivered
orderDecoder : Decoder Order_
orderDecoder =
decode Order_
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "petId" (Decode.nullable Decode.int) Nothing
|> optional "quantity" (Decode.nullable Decode.int) Nothing
|> optional "shipDate" (Decode.nullable dateTimeDecoder) Nothing
|> optional "status" (Decode.nullable statusDecoder) Nothing
|> optional "complete" (Decode.nullable Decode.bool) (Just False)
orderEncoder : Order_ -> Encode.Value
orderEncoder model =
Encode.object
[ ( "id", withDefault Encode.null (map Encode.int model.id) )
, ( "petId", withDefault Encode.null (map Encode.int model.petId) )
, ( "quantity", withDefault Encode.null (map Encode.int model.quantity) )
, ( "shipDate", withDefault Encode.null (map dateTimeEncoder model.shipDate) )
, ( "status", withDefault Encode.null (map statusEncoder model.status) )
, ( "complete", withDefault Encode.null (map Encode.bool model.complete) )
]
statusDecoder : Decoder Status
statusDecoder =
Decode.string
|> Decode.andThen (\str ->
case str of
"placed" ->
Decode.succeed Placed
"approved" ->
Decode.succeed Approved
"delivered" ->
Decode.succeed Delivered
other ->
Decode.fail <| "Unknown type: " ++ other
)
statusEncoder : Status -> Encode.Value
statusEncoder model =
case model of
Placed ->
Encode.string "placed"
Approved ->
Encode.string "approved"
Delivered ->
Encode.string "delivered"

View File

@ -0,0 +1,98 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Data.Pet exposing (Pet, Status(..), petDecoder, petEncoder)
import Data.Category exposing (Category, categoryDecoder, categoryEncoder)
import Data.Tag exposing (Tag, tagDecoder, tagEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{-| A pet for sale in the pet store
-}
type alias Pet =
{ id : Maybe Int
, category : Maybe Category
, name : String
, photoUrls : List String
, tags : Maybe (List Tag)
, status : Maybe Status
}
type Status
= Available
| Pending
| Sold
petDecoder : Decoder Pet
petDecoder =
decode Pet
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "category" (Decode.nullable categoryDecoder) Nothing
|> required "name" Decode.string
|> required "photoUrls" (Decode.list Decode.string)
|> optional "tags" (Decode.nullable (Decode.list tagDecoder)) Nothing
|> optional "status" (Decode.nullable statusDecoder) Nothing
petEncoder : Pet -> Encode.Value
petEncoder model =
Encode.object
[ ( "id", withDefault Encode.null (map Encode.int model.id) )
, ( "category", withDefault Encode.null (map categoryEncoder model.category) )
, ( "name", Encode.string model.name )
, ( "photoUrls", (Encode.list << List.map Encode.string) model.photoUrls )
, ( "tags", withDefault Encode.null (map (Encode.list << List.map tagEncoder) model.tags) )
, ( "status", withDefault Encode.null (map statusEncoder model.status) )
]
statusDecoder : Decoder Status
statusDecoder =
Decode.string
|> Decode.andThen (\str ->
case str of
"available" ->
Decode.succeed Available
"pending" ->
Decode.succeed Pending
"sold" ->
Decode.succeed Sold
other ->
Decode.fail <| "Unknown type: " ++ other
)
statusEncoder : Status -> Encode.Value
statusEncoder model =
case model of
Available ->
Encode.string "available"
Pending ->
Encode.string "pending"
Sold ->
Encode.string "sold"

View File

@ -0,0 +1,43 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Data.Tag exposing (Tag, tagDecoder, tagEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{-| A tag for a pet
-}
type alias Tag =
{ id : Maybe Int
, name : Maybe String
}
tagDecoder : Decoder Tag
tagDecoder =
decode Tag
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "name" (Decode.nullable Decode.string) Nothing
tagEncoder : Tag -> Encode.Value
tagEncoder model =
Encode.object
[ ( "id", withDefault Encode.null (map Encode.int model.id) )
, ( "name", withDefault Encode.null (map Encode.string model.name) )
]

View File

@ -0,0 +1,61 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Data.User exposing (User, userDecoder, userEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
{-| A User who is purchasing from the pet store
-}
type alias User =
{ id : Maybe Int
, username : Maybe String
, firstName : Maybe String
, lastName : Maybe String
, email : Maybe String
, password : Maybe String
, phone : Maybe String
, userStatus : Maybe Int
}
userDecoder : Decoder User
userDecoder =
decode User
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "username" (Decode.nullable Decode.string) Nothing
|> optional "firstName" (Decode.nullable Decode.string) Nothing
|> optional "lastName" (Decode.nullable Decode.string) Nothing
|> optional "email" (Decode.nullable Decode.string) Nothing
|> optional "password" (Decode.nullable Decode.string) Nothing
|> optional "phone" (Decode.nullable Decode.string) Nothing
|> optional "userStatus" (Decode.nullable Decode.int) Nothing
userEncoder : User -> Encode.Value
userEncoder model =
Encode.object
[ ( "id", withDefault Encode.null (map Encode.int model.id) )
, ( "username", withDefault Encode.null (map Encode.string model.username) )
, ( "firstName", withDefault Encode.null (map Encode.string model.firstName) )
, ( "lastName", withDefault Encode.null (map Encode.string model.lastName) )
, ( "email", withDefault Encode.null (map Encode.string model.email) )
, ( "password", withDefault Encode.null (map Encode.string model.password) )
, ( "phone", withDefault Encode.null (map Encode.string model.phone) )
, ( "userStatus", withDefault Encode.null (map Encode.int model.userStatus) )
]

View File

@ -0,0 +1,32 @@
module DateOnly exposing (DateOnly, dateOnlyDecoder, dateOnlyEncoder)
import Date
import Date.Extra exposing (fromIsoString, toFormattedString)
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result
type alias DateOnly =
Date.Date
dateOnlyDecoder : Decoder DateOnly
dateOnlyDecoder =
Decode.string
|> Decode.andThen decodeIsoString
dateOnlyEncoder : DateOnly -> Encode.Value
dateOnlyEncoder model =
Encode.string <| toFormattedString "yyyy-MM-dd" model
decodeIsoString : String -> Decoder DateOnly
decodeIsoString str =
case fromIsoString str of
Result.Ok date ->
Decode.succeed date
Result.Err msg ->
Decode.fail msg

View File

@ -0,0 +1,32 @@
module DateTime exposing (DateTime, dateTimeDecoder, dateTimeEncoder)
import Date
import Date.Extra exposing (fromIsoString, toIsoString)
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result
type alias DateTime =
Date.Date
dateTimeDecoder : Decoder DateTime
dateTimeDecoder =
Decode.string
|> Decode.andThen decodeIsoString
dateTimeEncoder : DateTime -> Encode.Value
dateTimeEncoder model =
Encode.string <| toIsoString model
decodeIsoString : String -> Decoder DateTime
decodeIsoString str =
case fromIsoString str of
Result.Ok date ->
Decode.succeed date
Result.Err msg ->
Decode.fail msg

View File

@ -0,0 +1,60 @@
module Main exposing (main)
import Html exposing (Html)
main : Program Never Model Msg
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ value : Int
}
init : ( Model, Cmd Msg )
init =
( Model 0, Cmd.none )
-- UPDATE
type Msg
= NoOp
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
NoOp ->
( model, Cmd.none )
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Html Msg
view _ =
Html.text "main"

View File

@ -0,0 +1,134 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Request.Pet exposing (addPet, deletePet, findPetsByStatus, findPetsByTags, getPetById, updatePet, updatePetWithForm, uploadFile)
import Data.Pet exposing (Pet, petDecoder, petEncoder)
import Data.ApiResponse exposing (ApiResponse, apiResponseDecoder)
import Dict
import Http
import Json.Decode as Decode
basePath : String
basePath =
"http://petstore.swagger.io/v2"
addPet : Pet -> Http.Request ()
addPet model =
{ method = "POST"
, url = basePath ++ "/pet"
, headers = []
, body = Http.jsonBody <| petEncoder model
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
deletePet : Int -> Http.Request ()
deletePet petId =
{ method = "DELETE"
, url = basePath ++ "/pet/" ++ toString petId
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| Multiple status values can be provided with comma separated strings
-}
findPetsByStatus : Http.Request (List Pet)
findPetsByStatus =
{ method = "GET"
, url = basePath ++ "/pet/findByStatus"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson (Decode.list petDecoder)
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
-}
findPetsByTags : Http.Request (List Pet)
findPetsByTags =
{ method = "GET"
, url = basePath ++ "/pet/findByTags"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson (Decode.list petDecoder)
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| Returns a single pet
-}
getPetById : Int -> Http.Request Pet
getPetById petId =
{ method = "GET"
, url = basePath ++ "/pet/" ++ toString petId
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson petDecoder
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
updatePet : Pet -> Http.Request ()
updatePet model =
{ method = "PUT"
, url = basePath ++ "/pet"
, headers = []
, body = Http.jsonBody <| petEncoder model
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
updatePetWithForm : Int -> Http.Request ()
updatePetWithForm petId =
{ method = "POST"
, url = basePath ++ "/pet/" ++ toString petId
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
uploadFile : Int -> Http.Request ApiResponse
uploadFile petId =
{ method = "POST"
, url = basePath ++ "/pet/" ++ toString petId ++ "/uploadImage"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson apiResponseDecoder
, timeout = Just 30000
, withCredentials = False
}
|> Http.request

View File

@ -0,0 +1,81 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Request.Store exposing (deleteOrder, getInventory, getOrderById, placeOrder)
import Data.Order_ exposing (Order_, orderDecoder, orderEncoder)
import Dict
import Http
import Json.Decode as Decode
basePath : String
basePath =
"http://petstore.swagger.io/v2"
{-| For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
-}
deleteOrder : String -> Http.Request ()
deleteOrder orderId =
{ method = "DELETE"
, url = basePath ++ "/store/order/" ++ orderId
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| Returns a map of status codes to quantities
-}
getInventory : Http.Request (Dict.Dict String Int)
getInventory =
{ method = "GET"
, url = basePath ++ "/store/inventory"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson (Decode.dict Decode.int)
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
-}
getOrderById : Int -> Http.Request Order_
getOrderById orderId =
{ method = "GET"
, url = basePath ++ "/store/order/" ++ toString orderId
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson orderDecoder
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
placeOrder : Order_ -> Http.Request Order_
placeOrder model =
{ method = "POST"
, url = basePath ++ "/store/order"
, headers = []
, body = Http.jsonBody <| orderEncoder model
, expect = Http.expectJson orderDecoder
, timeout = Just 30000
, withCredentials = False
}
|> Http.request

View File

@ -0,0 +1,133 @@
{-
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Do not edit this file manually.
-}
module Request.User exposing (createUser, createUsersWithArrayInput, createUsersWithListInput, deleteUser, getUserByName, loginUser, logoutUser, updateUser)
import Data.User exposing (User, userDecoder, userEncoder)
import Dict
import Http
import Json.Decode as Decode
basePath : String
basePath =
"http://petstore.swagger.io/v2"
{-| This can only be done by the logged in user.
-}
createUser : User -> Http.Request ()
createUser model =
{ method = "POST"
, url = basePath ++ "/user"
, headers = []
, body = Http.jsonBody <| userEncoder model
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
createUsersWithArrayInput : User -> Http.Request ()
createUsersWithArrayInput model =
{ method = "POST"
, url = basePath ++ "/user/createWithArray"
, headers = []
, body = Http.jsonBody <| userEncoder model
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
createUsersWithListInput : User -> Http.Request ()
createUsersWithListInput model =
{ method = "POST"
, url = basePath ++ "/user/createWithList"
, headers = []
, body = Http.jsonBody <| userEncoder model
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| This can only be done by the logged in user.
-}
deleteUser : String -> Http.Request ()
deleteUser username =
{ method = "DELETE"
, url = basePath ++ "/user/" ++ username
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
getUserByName : String -> Http.Request User
getUserByName username =
{ method = "GET"
, url = basePath ++ "/user/" ++ username
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson userDecoder
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
loginUser : Http.Request String
loginUser =
{ method = "GET"
, url = basePath ++ "/user/login"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson Decode.string
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
logoutUser : Http.Request ()
logoutUser =
{ method = "GET"
, url = basePath ++ "/user/logout"
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request
{-| This can only be done by the logged in user.
-}
updateUser : String -> User -> Http.Request ()
updateUser username model =
{ method = "PUT"
, url = basePath ++ "/user/" ++ username
, headers = []
, body = Http.jsonBody <| userEncoder model
, expect = Http.expectStringResponse (\_ -> Ok ())
, timeout = Just 30000
, withCredentials = False
}
|> Http.request

View File

@ -4,7 +4,7 @@
for ELM in `find src -name "*.elm"`
do
echo "Compiling $ELM"
elm make $ELM --output /dev/null --yes
elm make $ELM --output /dev/null
rc=$?
if [[ $rc != 0 ]]
then

View File

@ -0,0 +1,28 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.0",
"dependencies": {
"direct": {
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
"elm/browser": "1.0.0",
"elm/core": "1.0.0",
"elm/html": "1.0.0",
"elm/http": "1.0.0",
"elm/json": "1.0.0",
"elm/time": "1.0.0",
"rtfeldman/elm-iso8601-date-strings": "1.0.0"
},
"indirect": {
"elm/parser": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.0"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}

View File

@ -16,4 +16,3 @@ byteDecoder =
byteEncoder : Byte -> Encode.Value
byteEncoder model =
Encode.string model

View File

@ -13,7 +13,7 @@
module Data.ApiResponse exposing (ApiResponse, apiResponseDecoder, apiResponseEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing (optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
@ -29,7 +29,7 @@ type alias ApiResponse =
apiResponseDecoder : Decoder ApiResponse
apiResponseDecoder =
decode ApiResponse
Decode.succeed ApiResponse
|> optional "code" (Decode.nullable Decode.int) Nothing
|> optional "type" (Decode.nullable Decode.string) Nothing
|> optional "message" (Decode.nullable Decode.string) Nothing

View File

@ -13,7 +13,7 @@
module Data.Category exposing (Category, categoryDecoder, categoryEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing (optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
@ -28,7 +28,7 @@ type alias Category =
categoryDecoder : Decoder Category
categoryDecoder =
decode Category
Decode.succeed Category
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "name" (Decode.nullable Decode.string) Nothing

View File

@ -14,7 +14,7 @@ module Data.Order_ exposing (Order_, Status(..), orderDecoder, orderEncoder)
import DateTime exposing (DateTime, dateTimeDecoder, dateTimeEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing (optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
@ -40,7 +40,7 @@ type Status
orderDecoder : Decoder Order_
orderDecoder =
decode Order_
Decode.succeed Order_
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "petId" (Decode.nullable Decode.int) Nothing
|> optional "quantity" (Decode.nullable Decode.int) Nothing

View File

@ -15,7 +15,7 @@ module Data.Pet exposing (Pet, Status(..), petDecoder, petEncoder)
import Data.Category exposing (Category, categoryDecoder, categoryEncoder)
import Data.Tag exposing (Tag, tagDecoder, tagEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing (optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
@ -41,7 +41,7 @@ type Status
petDecoder : Decoder Pet
petDecoder =
decode Pet
Decode.succeed Pet
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "category" (Decode.nullable categoryDecoder) Nothing
|> required "name" Decode.string
@ -57,8 +57,8 @@ petEncoder model =
[ ( "id", withDefault Encode.null (map Encode.int model.id) )
, ( "category", withDefault Encode.null (map categoryEncoder model.category) )
, ( "name", Encode.string model.name )
, ( "photoUrls", (Encode.list << List.map Encode.string) model.photoUrls )
, ( "tags", withDefault Encode.null (map (Encode.list << List.map tagEncoder) model.tags) )
, ( "photoUrls", (Encode.list Encode.string) model.photoUrls )
, ( "tags", withDefault Encode.null (map (Encode.list tagEncoder) model.tags) )
, ( "status", withDefault Encode.null (map statusEncoder model.status) )
]

View File

@ -13,7 +13,7 @@
module Data.Tag exposing (Tag, tagDecoder, tagEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing (optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
@ -28,7 +28,7 @@ type alias Tag =
tagDecoder : Decoder Tag
tagDecoder =
decode Tag
Decode.succeed Tag
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "name" (Decode.nullable Decode.string) Nothing

View File

@ -13,7 +13,7 @@
module Data.User exposing (User, userDecoder, userEncoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (decode, optional, required)
import Json.Decode.Pipeline exposing (optional, required)
import Json.Encode as Encode
import Maybe exposing (map, withDefault)
@ -34,7 +34,7 @@ type alias User =
userDecoder : Decoder User
userDecoder =
decode User
Decode.succeed User
|> optional "id" (Decode.nullable Decode.int) Nothing
|> optional "username" (Decode.nullable Decode.string) Nothing
|> optional "firstName" (Decode.nullable Decode.string) Nothing

View File

@ -1,14 +1,14 @@
module DateOnly exposing (DateOnly, dateOnlyDecoder, dateOnlyEncoder)
import Date
import Date.Extra exposing (fromIsoString, toFormattedString)
import Iso8601
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result
import Time
type alias DateOnly =
Date.Date
Time.Posix
dateOnlyDecoder : Decoder DateOnly
@ -19,14 +19,16 @@ dateOnlyDecoder =
dateOnlyEncoder : DateOnly -> Encode.Value
dateOnlyEncoder model =
Encode.string <| toFormattedString "yyyy-MM-dd" model
Iso8601.fromTime model
|> String.left 10
|> Encode.string
decodeIsoString : String -> Decoder DateOnly
decodeIsoString str =
case fromIsoString str of
Result.Ok date ->
Decode.succeed date
case Iso8601.toTime (str ++ "T00:00:00.000Z") of
Result.Ok posix ->
Decode.succeed posix
Result.Err msg ->
Decode.fail msg
Result.Err _ ->
Decode.fail <| "Invalid date: " ++ str

View File

@ -1,14 +1,14 @@
module DateTime exposing (DateTime, dateTimeDecoder, dateTimeEncoder)
import Date
import Date.Extra exposing (fromIsoString, toIsoString)
import Iso8601
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
import Result
import Time
type alias DateTime =
Date.Date
Time.Posix
dateTimeDecoder : Decoder DateTime
@ -19,14 +19,14 @@ dateTimeDecoder =
dateTimeEncoder : DateTime -> Encode.Value
dateTimeEncoder model =
Encode.string <| toIsoString model
Encode.string <| Iso8601.fromTime model
decodeIsoString : String -> Decoder DateTime
decodeIsoString str =
case fromIsoString str of
Result.Ok date ->
Decode.succeed date
case Iso8601.toTime str of
Result.Ok posix ->
Decode.succeed posix
Result.Err msg ->
Decode.fail msg
Result.Err _ ->
Decode.fail <| "Invalid date: " ++ str

View File

@ -1,43 +1,61 @@
module Main exposing (..)
module Main exposing (main)
import Json.Decode as Decode
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import Http
import Browser
import Html exposing (Html)
main : Program Never Model Msg
main : Program () Model Msg
main =
Html.program
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ status : Maybe Int
{ value : Int
}
init : (Model, Cmd Msg)
init =
( Model Nothing, Cmd.none )
init : () -> ( Model, Cmd Msg )
init _ =
( Model 0, Cmd.none )
-- UPDATE
type Msg
= NoOp
update : Msg -> Model -> (Model, Cmd Msg)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
NoOp ->
( model, Cmd.none )
view : Model -> Html Msg
view model =
Html.text "main"
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Html Msg
view _ =
Html.text "main"

View File

@ -40,7 +40,7 @@ addPet model =
deletePet : Int -> Http.Request ()
deletePet petId =
{ method = "DELETE"
, url = basePath ++ "/pet/" ++ toString petId
, url = basePath ++ "/pet/" ++ String.fromInt petId
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
@ -85,7 +85,7 @@ findPetsByTags =
getPetById : Int -> Http.Request Pet
getPetById petId =
{ method = "GET"
, url = basePath ++ "/pet/" ++ toString petId
, url = basePath ++ "/pet/" ++ String.fromInt petId
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson petDecoder
@ -111,7 +111,7 @@ updatePet model =
updatePetWithForm : Int -> Http.Request ()
updatePetWithForm petId =
{ method = "POST"
, url = basePath ++ "/pet/" ++ toString petId
, url = basePath ++ "/pet/" ++ String.fromInt petId
, headers = []
, body = Http.emptyBody
, expect = Http.expectStringResponse (\_ -> Ok ())
@ -124,7 +124,7 @@ updatePetWithForm petId =
uploadFile : Int -> Http.Request ApiResponse
uploadFile petId =
{ method = "POST"
, url = basePath ++ "/pet/" ++ toString petId ++ "/uploadImage"
, url = basePath ++ "/pet/" ++ String.fromInt petId ++ "/uploadImage"
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson apiResponseDecoder

View File

@ -58,7 +58,7 @@ getInventory =
getOrderById : Int -> Http.Request Order_
getOrderById orderId =
{ method = "GET"
, url = basePath ++ "/store/order/" ++ toString orderId
, url = basePath ++ "/store/order/" ++ String.fromInt orderId
, headers = []
, body = Http.emptyBody
, expect = Http.expectJson orderDecoder

View File

@ -24,6 +24,8 @@ build:
- wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
- sudo apt-get update
- sudo apt-get install elixir
# install elm
- curl -SL https://github.com/elm/compiler/releases/download/0.19.0/binaries-for-linux.tar.gz | tar xzv -C /usr/local/bin
# install rebar3
- wget https://s3.amazonaws.com/rebar3/rebar3 && chmod +x rebar3 && cp rebar3 /usr/bin
# install php