forked from loafle/openapi-generator-original
[Scala] added new scala-cask generator for the cask framework (#18344)
* Ran `./new.sh -n scala-cask -s` to generate a new Scala Cask impl * removed scala-cask-petstore * Added Scala-cask param parser for BigDecimals * added scala cask to samples * splitting out validation and json * Added GitHub workflow support * regenerated cask samples * cask build fix for local builds * regenerated samples * trying to reproduce failed cask build. checking in compiles sources, which have been reformatted * reverted whaitespace change * cask fix - adding gitignored files * scala cask toLowreCase fix * scala cask toUpperCase fix * cask regenerated samples * improved exception handling for scala cask * File separator fix for windows * Noob fix for cask * regenerated api package * Removed environment variable settings, debug code * Updated samples * moved scala-cask output * Regenerated samples * scala cask fix * Updated scala cask settings for more typical package structure Removed cask client samples * cask - reran generate samples * Removed duplicate ScalaCaskServer entry * minor enhancements * update samples * update templates --------- Co-authored-by: aaron.pritzlaff <aaron@kindservices.co.uk>
This commit is contained in:
41
samples/server/petstore/scala-cask/.github/workflows/bulidAndPublish.yml
vendored
Normal file
41
samples/server/petstore/scala-cask/.github/workflows/bulidAndPublish.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Scala CI with sbt
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache sbt dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.ivy2/cache
|
||||
~/.sbt
|
||||
~/.m2
|
||||
key: ${{ runner.os }}-sbt-${{ hashFiles('**/*.sbt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-sbt-
|
||||
|
||||
- name: Build with sbt
|
||||
run: sbt clean compile
|
||||
|
||||
- name: Test with sbt
|
||||
run: sbt test
|
||||
|
||||
- name: Publish to GitHub Packages
|
||||
run: sbt publish
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
25
samples/server/petstore/scala-cask/.gitignore
vendored
Normal file
25
samples/server/petstore/scala-cask/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# scala specific
|
||||
*.class
|
||||
*.log
|
||||
|
||||
# sbt specific
|
||||
.cache
|
||||
.history
|
||||
.lib/
|
||||
dist/*
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
project/plugins/project/
|
||||
|
||||
# Scala-IDE specific
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
# Mill specific
|
||||
out
|
||||
|
||||
# IntelliJ specific
|
||||
.idea
|
||||
*.iml
|
||||
23
samples/server/petstore/scala-cask/.openapi-generator-ignore
Normal file
23
samples/server/petstore/scala-cask/.openapi-generator-ignore
Normal 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
|
||||
39
samples/server/petstore/scala-cask/.openapi-generator/FILES
Normal file
39
samples/server/petstore/scala-cask/.openapi-generator/FILES
Normal file
@@ -0,0 +1,39 @@
|
||||
.github/workflows/bulidAndPublish.yml
|
||||
.gitignore
|
||||
.scalafmt.conf
|
||||
README.md
|
||||
README.md
|
||||
build.sbt
|
||||
build.sc
|
||||
example/Dockerfile
|
||||
example/Server.scala
|
||||
project/build.properties
|
||||
project/plugins.sbt
|
||||
src/main/scala/sample/cask/AppRoutes.scala
|
||||
src/main/scala/sample/cask/BaseApp.scala
|
||||
src/main/scala/sample/cask/ExampleApp.scala
|
||||
src/main/scala/sample/cask/api/OpenApiRoutes.scala
|
||||
src/main/scala/sample/cask/api/PetRoutes.scala
|
||||
src/main/scala/sample/cask/api/PetRoutes.scala
|
||||
src/main/scala/sample/cask/api/PetService.scala
|
||||
src/main/scala/sample/cask/api/StoreRoutes.scala
|
||||
src/main/scala/sample/cask/api/StoreRoutes.scala
|
||||
src/main/scala/sample/cask/api/StoreService.scala
|
||||
src/main/scala/sample/cask/api/UserRoutes.scala
|
||||
src/main/scala/sample/cask/api/UserRoutes.scala
|
||||
src/main/scala/sample/cask/api/UserService.scala
|
||||
src/main/scala/sample/cask/api/package.scala
|
||||
src/main/scala/sample/cask/model/ApiResponse.scala
|
||||
src/main/scala/sample/cask/model/ApiResponseData.scala
|
||||
src/main/scala/sample/cask/model/Category.scala
|
||||
src/main/scala/sample/cask/model/CategoryData.scala
|
||||
src/main/scala/sample/cask/model/Order.scala
|
||||
src/main/scala/sample/cask/model/OrderData.scala
|
||||
src/main/scala/sample/cask/model/Pet.scala
|
||||
src/main/scala/sample/cask/model/PetData.scala
|
||||
src/main/scala/sample/cask/model/Tag.scala
|
||||
src/main/scala/sample/cask/model/TagData.scala
|
||||
src/main/scala/sample/cask/model/User.scala
|
||||
src/main/scala/sample/cask/model/UserData.scala
|
||||
src/main/scala/sample/cask/model/package.scala
|
||||
src/main/scala/sample/cask/package.scala
|
||||
@@ -0,0 +1 @@
|
||||
7.5.0-SNAPSHOT
|
||||
4
samples/server/petstore/scala-cask/.scalafmt.conf
Normal file
4
samples/server/petstore/scala-cask/.scalafmt.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
version = 3.6.1
|
||||
align.preset = more // For pretty alignment.
|
||||
maxColumn = 100
|
||||
runner.dialect = scala3
|
||||
96
samples/server/petstore/scala-cask/README.md
Normal file
96
samples/server/petstore/scala-cask/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# REST Service
|
||||
|
||||
This project contains the data models and REST services, generated from the [openapi-generator](https://github.com/OpenAPITools/openapi-generator) project.
|
||||
|
||||
The server implementation is based on Li's excellent [cask](https://com-lihaoyi.github.io/cask/) library.
|
||||
|
||||
# How to use this code
|
||||
|
||||
This code was designed so that it can be packaged up and semantically-versioned alongside your open-api schema.
|
||||
|
||||
That approach supports having separate "contract" repositories for microservice projects, where the pipeline for the
|
||||
contract repo might produce versioned jar artefacts which can then easily be brought in / referenced by a separate service project which simply
|
||||
implements the business logic.
|
||||
|
||||
You can read more about this approach [here](https://github.com/kindservices/contract-first-rest)
|
||||
|
||||
# How to implement your business logic
|
||||
There are a few options for using this code/applying your business logic for the services.
|
||||
|
||||
## Option 1 (preferred): Package and publish this boilerplate
|
||||
Typically, OpenApi templates are written to generate code which co-exists alongside the handwritten business logic.
|
||||
|
||||
While that works, it's also not ideal:
|
||||
* You have to ensure the generated code isn't checked in
|
||||
* Team members, build pipelines, etc all have to regenerate and recompile the same boilerplate code over and over
|
||||
* People can encounter IDE issues with generated code
|
||||
|
||||
Instead, you have the option of simply packaging/publishing this generated code, and then allowing service implementations
|
||||
to simply bring in the published code as a dependency.
|
||||
|
||||
The steps to do that are:
|
||||
|
||||
### Build/Publish
|
||||
This project is built using [sbt](https://www.scala-sbt.org/download/), so you can run `sbt publish` (or `sbt publishLocal`)
|
||||
|
||||
Or, for a zero-install docker build:
|
||||
```bash
|
||||
docker run -it --rm -v $(pwd):/app -w /app sbtscala/scala-sbt:eclipse-temurin-17.0.4_1.7.1_3.2.0 sbt publishLocal
|
||||
```
|
||||
|
||||
### Create a new separate implementation project
|
||||
Once published, you can create your server implementation in a new, clean, separate project based on [the example](./example)
|
||||
|
||||
This means all the boilerplate endpoint and model code is brought in as "just another jar", and you're free to
|
||||
create a greenfield project in whatever language (scala, java, kotlin) and build system of your choosing.
|
||||
|
||||
We show a simple, minimalistic example of a starting point in [the example project](./example)
|
||||
|
||||
## Option 2: Extend this generated example
|
||||
You can configure this project (for instance, setting up your own .gitignore rules and scripts) to leave the generated code as-is
|
||||
and provide your implementation alongside the generated code.
|
||||
|
||||
The place to start is by providing your own implementation of the Services defined in the `api` package -
|
||||
perhaps by creating your 'MyService.scala' code in a new `impl` package.
|
||||
|
||||
You then have several options for how to wire those in:
|
||||
|
||||
1) Create a new BaseApp instance to create your own Main entry point
|
||||
Follow the pattern in App.scala, but by passing your own implementations to BaseApp,
|
||||
ensuring you call `start` to start the server
|
||||
|
||||
```bash
|
||||
@main def run() = BaseApp(/* your services here/*).start()
|
||||
```
|
||||
|
||||
2) Extend either BaseApp class or mix in the AppRoutes trait
|
||||
You can create your own main entry point with further control of the main cask app by extending
|
||||
the BaseApp or otherwise creating your own CaskApp which mixes in the AppRoutes
|
||||
|
||||
```bash
|
||||
object MyApp extends BaseApp(/* your services here/*) {
|
||||
// any overrides, new routes, etc here
|
||||
start()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# Customising the generated code
|
||||
|
||||
A typical config.yml used to alter the generated code may look like this:
|
||||
```
|
||||
groupId: "ex.amp.le"
|
||||
artifactId: "pets-test"
|
||||
apiPackage: "ex.ample.api"
|
||||
modelPackage: "ex.ample.model"
|
||||
```
|
||||
|
||||
Which you would then pass to the generator like this:
|
||||
```
|
||||
docker run --rm \
|
||||
-v ${PWD}:/local openapitools/openapi-generator-cli generate \
|
||||
-i https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.yaml \
|
||||
-g scala-cask \
|
||||
-c /local/config.yml \
|
||||
-o /local/path/to/output_dir
|
||||
```
|
||||
29
samples/server/petstore/scala-cask/build.sbt
Normal file
29
samples/server/petstore/scala-cask/build.sbt
Normal file
@@ -0,0 +1,29 @@
|
||||
name := "scala-cask-petstore"
|
||||
organization:="cask.groupId"
|
||||
version := "0.0.1-SNAPSHOT"
|
||||
scalaVersion := "3.3.1"
|
||||
scalafmtOnCompile := true
|
||||
libraryDependencies ++= Seq(
|
||||
"com.lihaoyi" %% "cask" % "0.9.2" ,
|
||||
"com.lihaoyi" %% "upickle" % "3.2.0",
|
||||
"org.scalatest" %% "scalatest" % "3.2.18" % Test
|
||||
)
|
||||
|
||||
publishMavenStyle := true
|
||||
|
||||
val githubUser = "GIT_USER_ID"
|
||||
val githubRepo = "GIT_REPO_ID"
|
||||
publishTo := Some("GitHub Package Registry" at s"https://maven.pkg.github.com/$githubUser/$githubRepo")
|
||||
|
||||
sys.env.get("GITHUB_TOKEN") match {
|
||||
case Some(token) if !token.isEmpty =>
|
||||
credentials += Credentials(
|
||||
"GitHub Package Registry",
|
||||
"maven.pkg.github.com",
|
||||
githubUser,
|
||||
token
|
||||
)
|
||||
case _ =>
|
||||
println("\n\t\tGITHUB_TOKEN not set - assuming a local build\n\n")
|
||||
credentials ++= Nil
|
||||
}
|
||||
43
samples/server/petstore/scala-cask/build.sc
Normal file
43
samples/server/petstore/scala-cask/build.sc
Normal file
@@ -0,0 +1,43 @@
|
||||
import mill._, scalalib._, scalafmt._, publish._
|
||||
|
||||
// Mill build file (see https://mill-build.com/mill/Intro_to_Mill.html).
|
||||
// run with:
|
||||
//
|
||||
// mill _.compile
|
||||
// mill _.reformat
|
||||
// mill _.publishLocal
|
||||
// mill _.test.test
|
||||
object scala-cask-petstore extends SbtModule with ScalafmtModule with PublishModule {
|
||||
def scalaVersion = "3.3.1"
|
||||
|
||||
def pomSettings = PomSettings(
|
||||
description = "scala-cask-petstore",
|
||||
organization = "cask.groupId",
|
||||
url = "https://github.com/<username>/scala-cask-petstore",
|
||||
licenses = Seq(License.MIT),
|
||||
versionControl = VersionControl.github("<username>", "scala-cask-petstore"),
|
||||
developers = Seq(
|
||||
// Developer("<username>", "<your name>", "https://github.com/<you>")
|
||||
)
|
||||
)
|
||||
|
||||
def publishVersion: mill.T[String] = T("0.0.1-SNAPSHOT")
|
||||
|
||||
def ivyDeps = Agg(
|
||||
ivy"com.lihaoyi::cask:0.9.2" ,
|
||||
ivy"com.lihaoyi::upickle:3.2.0"
|
||||
)
|
||||
|
||||
override def sources = T.sources(millSourcePath / os.up / "src" / "main" / "scala")
|
||||
override def resources = T.sources(millSourcePath / os.up / "src" / "main" / "resources")
|
||||
|
||||
object test extends SbtModuleTests {
|
||||
def ivyDeps = Agg(
|
||||
ivy"org.scalactic::scalactic:3.2.18",
|
||||
ivy"org.scalatest::scalatest:3.2.18"
|
||||
)
|
||||
|
||||
def testFramework = "org.scalatest.tools.Framework"
|
||||
override def sources = T.sources(millSourcePath / os.up / "src" / "test" / "scala")
|
||||
}
|
||||
}
|
||||
13
samples/server/petstore/scala-cask/example/Dockerfile
Normal file
13
samples/server/petstore/scala-cask/example/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM virtuslab/scala-cli:latest as build
|
||||
WORKDIR /app
|
||||
COPY ./Server.scala /app/
|
||||
# note: this assumes a published server stub jar.
|
||||
# If you've published this locally, you would need to copy those into this image,
|
||||
# perhaps by using coursier fetch
|
||||
RUN scala-cli --power package /app/Server.scala --assembly -o app.jar
|
||||
|
||||
# The main image
|
||||
FROM openjdk:23-slim
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/app.jar /app/
|
||||
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
|
||||
61
samples/server/petstore/scala-cask/example/Server.scala
Normal file
61
samples/server/petstore/scala-cask/example/Server.scala
Normal file
@@ -0,0 +1,61 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "cask.groupId::scala-cask-petstore:0.0.1-SNAPSHOT"
|
||||
//> using repositories https://maven.pkg.github.com/GIT_USER_ID/GIT_REPO_ID
|
||||
|
||||
|
||||
/**
|
||||
* This single file can contain the business logic for a REST service.
|
||||
* ====================================
|
||||
* == zero-install build with docker ==
|
||||
* ====================================
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* docker build . -t scala-cask-petstore:latest
|
||||
* ```
|
||||
* ======================
|
||||
* == Building Locally ==
|
||||
* ======================
|
||||
* This project can be built using [[scala-clit][https://scala-cli.virtuslab.org]]
|
||||
*
|
||||
* To simply run the project
|
||||
* ```
|
||||
* scala-cli Server.scala
|
||||
* ```
|
||||
*
|
||||
* To create a runnable jar, run:
|
||||
* ```
|
||||
* scala-cli --power package Server.scala -o app-assembly --assembly
|
||||
* ```
|
||||
*
|
||||
* To produce a docker image (no need for the Dockerfile), run:
|
||||
* ```
|
||||
* scala-cli --power package --docker Server.scala --docker-image-repository app-docker
|
||||
* ```
|
||||
*
|
||||
* To generate an IDE project:
|
||||
* ```
|
||||
* scala-cli setup-ide . --scala 3.3
|
||||
* ```
|
||||
*/
|
||||
package app
|
||||
|
||||
import cask.groupId.server.BaseApp
|
||||
import sample.cask.api.*
|
||||
import sample.cask.model.*
|
||||
|
||||
import java.io.File
|
||||
|
||||
// TODO - write your business logic for your services here (the defaults all return 'not implemented'):
|
||||
val myPetService : PetService = PetService() // <-- replace this with your implementation
|
||||
val myStoreService : StoreService = StoreService() // <-- replace this with your implementation
|
||||
val myUserService : UserService = UserService() // <-- replace this with your implementation
|
||||
|
||||
/** This is your main entry point for your REST service
|
||||
* It extends BaseApp which defines the business logic for your services
|
||||
*/
|
||||
object Server extends BaseApp(appPetService = myPetService,
|
||||
appStoreService = myStoreService,
|
||||
appUserService = myUserService):
|
||||
start()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
sbt.version=1.9.9
|
||||
3
samples/server/petstore/scala-cask/project/plugins.sbt
Normal file
3
samples/server/petstore/scala-cask/project/plugins.sbt
Normal file
@@ -0,0 +1,3 @@
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")
|
||||
|
||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
|
||||
1032
samples/server/petstore/scala-cask/src/main/resources/openapi.json
Normal file
1032
samples/server/petstore/scala-cask/src/main/resources/openapi.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.9.2"
|
||||
//> using lib "com.lihaoyi::scalatags:0.8.2"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this file was generated from app.mustache
|
||||
package cask.groupId.server
|
||||
|
||||
import _root_.sample.cask.model.*
|
||||
import _root_.sample.cask.api.*
|
||||
|
||||
/**
|
||||
* This trait encapsulates the business logic (services) and the
|
||||
* http routes which handle the http requests sent to those services.
|
||||
*
|
||||
* There are default 'not implemented' implementations for the service.
|
||||
*
|
||||
* If you wanted fine-grained control over the routes and services, you could
|
||||
* extend the cask.MainRoutes and mix in this trait by using this:
|
||||
*
|
||||
* \{\{\{
|
||||
* override def allRoutes = appRoutes
|
||||
* \}\}\}
|
||||
*
|
||||
* More typically, however, you would extend the 'BaseApp' class
|
||||
*/
|
||||
trait AppRoutes {
|
||||
def appPetService : PetService = PetService()
|
||||
def routeForPet : PetRoutes = PetRoutes(appPetService)
|
||||
def appStoreService : StoreService = StoreService()
|
||||
def routeForStore : StoreRoutes = StoreRoutes(appStoreService)
|
||||
def appUserService : UserService = UserService()
|
||||
def routeForUser : UserRoutes = UserRoutes(appUserService)
|
||||
|
||||
def appRoutes = Seq(
|
||||
routeForPet ,
|
||||
routeForStore ,
|
||||
routeForUser
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.9.2"
|
||||
//> using lib "com.lihaoyi::scalatags:0.8.2"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this file was generated from app.mustache
|
||||
package cask.groupId.server
|
||||
|
||||
import _root_.sample.cask.model.*
|
||||
import _root_.sample.cask.api.*
|
||||
|
||||
/**
|
||||
* This class was created with the intention of being extended by some runnable object,
|
||||
* passing in the custom business logic services
|
||||
*/
|
||||
class BaseApp(
|
||||
override val appPetService : PetService = PetService(),
|
||||
|
||||
override val appStoreService : StoreService = StoreService(),
|
||||
|
||||
override val appUserService : UserService = UserService(),
|
||||
override val port : Int = sys.env.get("PORT").map(_.toInt).getOrElse(8080)) extends cask.MainRoutes with AppRoutes {
|
||||
|
||||
/** routes for the UI
|
||||
* Subclasses can override to turn this off
|
||||
*/
|
||||
def openApiRoute: Option[cask.Routes] = Option(OpenApiRoutes(port))
|
||||
|
||||
override def allRoutes = appRoutes ++ openApiRoute
|
||||
|
||||
|
||||
override def host: String = "0.0.0.0"
|
||||
|
||||
def start() = locally {
|
||||
initialize()
|
||||
println(box(s""" 🚀 browse to localhost:$port 🚀
|
||||
| host : $host
|
||||
| port : $port
|
||||
| verbose : $verbose
|
||||
| debugMode : $debugMode
|
||||
|""".stripMargin))
|
||||
|
||||
// if java.awt.Desktop.isDesktopSupported then {
|
||||
// java.awt.Desktop.getDesktop.browse(new java.net.URI(s"http://localhost:${port}"))
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.9.2"
|
||||
//> using lib "com.lihaoyi::scalatags:0.8.2"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this file was generated from app.mustache
|
||||
package cask.groupId.server
|
||||
|
||||
import _root_.sample.cask.model.*
|
||||
import _root_.sample.cask.api.*
|
||||
|
||||
/**
|
||||
* This is an example of how you might extends BaseApp for a runnable application.
|
||||
*
|
||||
* See the README.md for how to create your own app
|
||||
*/
|
||||
object ExampleApp extends BaseApp() {
|
||||
start()
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// generated from openapiRoute.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import cask.model.Response
|
||||
|
||||
import java.nio.file.{Files, Path, Paths}
|
||||
|
||||
/**
|
||||
* This code will try and download the swagger UI static files on startup
|
||||
*
|
||||
* That behaviour can be altered by:
|
||||
* - setting the environment variable SWAGGER_ON to false
|
||||
* - setting the environment variable SWAGGER_UI_URL to either the URL of a swagger UI zip or setting it to the empty string
|
||||
*
|
||||
*/
|
||||
object OpenApiRoutes {
|
||||
|
||||
def swaggerUIUrl: Option[String] = {
|
||||
// flag to turn SWAGGER off
|
||||
def useSwaggerUI = sys.env.get("SWAGGER_ON").map(_.toBoolean).getOrElse(true)
|
||||
|
||||
val defaultUrl = "https://github.com/swagger-api/swagger-ui/archive/refs/tags/v5.11.9.zip"
|
||||
Option(sys.env.getOrElse("SWAGGER_UI_URL", defaultUrl))
|
||||
.map(_.trim)
|
||||
.filterNot(_.isEmpty)
|
||||
.filter(_ => useSwaggerUI)
|
||||
}
|
||||
def apply(localPort: Int) = new OpenApiRoutes(localPort, swaggerUIUrl)
|
||||
}
|
||||
|
||||
class OpenApiRoutes(localPort: Int, swaggerUrl: Option[String]) extends cask.Routes {
|
||||
|
||||
def openApiDir = "ui"
|
||||
|
||||
@cask.get("/")
|
||||
def index() = cask.Redirect("/ui/index.html")
|
||||
|
||||
@cask.staticFiles("/ui")
|
||||
def staticUI() = openApiDir
|
||||
|
||||
@cask.staticResources("/openapi.json")
|
||||
def staticOpenApi() = "openapi.json"
|
||||
|
||||
/** This code will try and download the swagger UI artefacts to a local directory to serve up
|
||||
*/
|
||||
object extract {
|
||||
|
||||
def openApiDirPath: Path = Paths.get(openApiDir)
|
||||
def hasSwagger = Files.exists(openApiDirPath) && Files.isDirectory(openApiDirPath)
|
||||
|
||||
import java.io.{BufferedInputStream, FileOutputStream, InputStream}
|
||||
import java.net.URL
|
||||
import java.util.zip.{ZipEntry, ZipInputStream}
|
||||
import scala.util.Using
|
||||
|
||||
def apply(url: String) = {
|
||||
if !hasSwagger then downloadAndExtractZip(url, openApiDir)
|
||||
}
|
||||
|
||||
def downloadAndExtractZip(url: String, outputDir: String): Unit = {
|
||||
val urlConn = new URL(url).openConnection()
|
||||
urlConn.setRequestProperty("User-Agent", "Mozilla/5.0")
|
||||
|
||||
Using(urlConn.getInputStream) { inputStream =>
|
||||
val zipIn = new ZipInputStream(new BufferedInputStream(inputStream))
|
||||
LazyList.continually(zipIn.getNextEntry).takeWhile(_ != null).foreach { entry =>
|
||||
|
||||
def isDist = entry.getName.contains("/dist/")
|
||||
def isNotMap = !entry.getName.endsWith(".map")
|
||||
|
||||
if (!entry.isDirectory && isDist && isNotMap) {
|
||||
val fileName = entry.getName.split("/").last
|
||||
extractFile(entry.getName, zipIn, s"$outputDir/$fileName")
|
||||
}
|
||||
zipIn.closeEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def extractFile(name: String, zipIn: ZipInputStream, filePath: String): Unit = {
|
||||
val fullPath = Paths.get(filePath).toAbsolutePath
|
||||
if !Files.exists(fullPath.getParent) then {
|
||||
Files.createDirectories(fullPath.getParent)
|
||||
}
|
||||
|
||||
// config hack - we replace the default url from this swagger conf to use our localhost
|
||||
//
|
||||
if name.endsWith("swagger-initializer.js") then {
|
||||
val textLines = scala.io.Source.fromInputStream(zipIn).getLines().map {
|
||||
case line if line.contains("url:") =>
|
||||
s""" url: "http://localhost:$localPort/openapi.json","""
|
||||
case line => line
|
||||
}
|
||||
|
||||
// keeping this compatible for java 8, where this is from >= java 11:
|
||||
// Files.writeString(fullPath, textLines.mkString("\n"))
|
||||
scala.util.Using(new java.io.PrintWriter(fullPath.toFile))(_.write(textLines.mkString("\n")))
|
||||
} else {
|
||||
Using(new FileOutputStream(filePath)) { outputStream =>
|
||||
val buffer = new Array[Byte](1024)
|
||||
LazyList
|
||||
.continually(zipIn.read(buffer))
|
||||
.takeWhile(_ != -1)
|
||||
.foreach(outputStream.write(buffer, 0, _))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extract the swagger UI resources to our local directory
|
||||
swaggerUrl.foreach(url => extract(url))
|
||||
|
||||
initialize()
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this is generated from apiRoutes.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import sample.cask.model.*
|
||||
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
import sample.cask.model.ApiResponse
|
||||
import java.io.File
|
||||
import sample.cask.model.Pet
|
||||
|
||||
class PetRoutes(service : PetService) extends cask.Routes {
|
||||
|
||||
// route group for routeWorkAroundForPOSTPet
|
||||
@cask.post("/pet", true)
|
||||
def routeWorkAroundForPOSTPet(request: cask.Request) = {
|
||||
request.remainingPathSegments match {
|
||||
case Seq() => addPet(request)
|
||||
case Seq(petId) => updatePetWithForm(petId.toLong,request)
|
||||
case Seq(petId,"uploadImage") => uploadFile(petId.toLong,request)
|
||||
case _ => cask.Response("Not Found", statusCode = 404)
|
||||
}
|
||||
}
|
||||
// route group for routeWorkAroundForGETPet
|
||||
@cask.get("/pet", true)
|
||||
def routeWorkAroundForGETPet(request: cask.Request,status : Seq[String] = Nil,tags : Seq[String] = Nil) = {
|
||||
request.remainingPathSegments match {
|
||||
case Seq("findByStatus") => findPetsByStatus(request,status)
|
||||
case Seq("findByTags") => findPetsByTags(request,tags)
|
||||
case Seq(petId) => getPetById(petId.toLong,request)
|
||||
case _ => cask.Response("Not Found", statusCode = 404)
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a new pet to the store
|
||||
*
|
||||
*/
|
||||
// conflicts with [/pet/{petId}, /pet/{petId}/uploadImage, /pet] after/pet, ignoring @cask.post("/pet")
|
||||
def addPet(request: cask.Request) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
petData <- Parsed.eval(PetData.fromJsonString(request.bodyAsString)).mapError(e => s"Error parsing json as Pet from >${request.bodyAsString}< : ${e}") /* not array or map */
|
||||
pet <- Parsed.fromTry(petData.validated(failFast))
|
||||
result <- Parsed.eval(service.addPet(pet))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Deletes a pet
|
||||
*
|
||||
*/
|
||||
@cask.delete("/pet/:petId")
|
||||
def deletePet(petId : Long, request: cask.Request) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
petId <- Parsed(petId)
|
||||
apiKey <- request.headerSingleValueOptional("apiKey")
|
||||
result <- Parsed.eval(service.deletePet(petId, apiKey))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Finds Pets by status
|
||||
*
|
||||
*/
|
||||
// conflicts with [/pet/{petId}, /pet/findByStatus, /pet/findByTags] after/pet, ignoring @cask.get("/pet/findByStatus")
|
||||
def findPetsByStatus(request: cask.Request, status : Seq[String]) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
result <- Parsed.eval(service.findPetsByStatus(status))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Finds Pets by tags
|
||||
*
|
||||
*/
|
||||
// conflicts with [/pet/{petId}, /pet/findByStatus, /pet/findByTags] after/pet, ignoring @cask.get("/pet/findByTags")
|
||||
def findPetsByTags(request: cask.Request, tags : Seq[String]) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
result <- Parsed.eval(service.findPetsByTags(tags))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Find pet by ID
|
||||
*
|
||||
*/
|
||||
// conflicts with [/pet/{petId}, /pet/findByStatus, /pet/findByTags] after/pet, ignoring @cask.get("/pet/:petId")
|
||||
def getPetById(petId : Long, request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
petId <- Parsed(petId)
|
||||
result <- Parsed.eval(service.getPetById(petId))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Update an existing pet
|
||||
*
|
||||
*/
|
||||
@cask.put("/pet")
|
||||
def updatePet(request: cask.Request) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
petData <- Parsed.eval(PetData.fromJsonString(request.bodyAsString)).mapError(e => s"Error parsing json as Pet from >${request.bodyAsString}< : ${e}") /* not array or map */
|
||||
pet <- Parsed.fromTry(petData.validated(failFast))
|
||||
result <- Parsed.eval(service.updatePet(pet))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Updates a pet in the store with form data
|
||||
*
|
||||
*/
|
||||
// conflicts with [/pet/{petId}, /pet/{petId}/uploadImage, /pet] after/pet, ignoring @cask.post("/pet/:petId")
|
||||
def updatePetWithForm(petId : Long, request: cask.Request) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
petId <- Parsed(petId)
|
||||
name <- request.formSingleValueOptional("name")
|
||||
status <- request.formSingleValueOptional("status")
|
||||
result <- Parsed.eval(service.updatePetWithForm(petId, name, status))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** uploads an image
|
||||
*
|
||||
*/
|
||||
// conflicts with [/pet/{petId}, /pet/{petId}/uploadImage, /pet] after/pet, ignoring @cask.post("/pet/:petId/uploadImage")
|
||||
def uploadFile(petId : Long, request: cask.Request) = {
|
||||
// auth method petstore_auth : oauth2, keyParamName:
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
petId <- Parsed(petId)
|
||||
additionalMetadata <- request.formSingleValueOptional("additionalMetadata")
|
||||
file <- request.formValueAsFileOptional("file")
|
||||
result <- Parsed.eval(service.uploadFile(petId, additionalMetadata, file))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
|
||||
initialize()
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// generated from apiService.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import _root_.sample.cask.model.ApiResponse
|
||||
import _root_.java.io.File
|
||||
import _root_.sample.cask.model.Pet
|
||||
|
||||
import _root_.sample.cask.model.*
|
||||
|
||||
object PetService {
|
||||
def apply() : PetService = new PetService {
|
||||
override def addPet(pet : Pet) : Pet = ???
|
||||
override def deletePet(petId : Long, apiKey : Option[String]) : Unit = ???
|
||||
override def findPetsByStatus(status : Seq[String]) : List[Pet] = ???
|
||||
override def findPetsByTags(tags : Seq[String]) : List[Pet] = ???
|
||||
override def getPetById(petId : Long) : Pet = ???
|
||||
override def updatePet(pet : Pet) : Pet = ???
|
||||
override def updatePetWithForm(petId : Long, name : Option[String], status : Option[String]) : Unit = ???
|
||||
override def uploadFile(petId : Long, additionalMetadata : Option[String], file : Option[File]) : ApiResponse = ???
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Pet business-logic
|
||||
*/
|
||||
trait PetService {
|
||||
/** Add a new pet to the store
|
||||
*
|
||||
* @return Pet
|
||||
*/
|
||||
def addPet(pet : Pet) : Pet
|
||||
/** Deletes a pet
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def deletePet(petId : Long, apiKey : Option[String]) : Unit
|
||||
/** Finds Pets by status
|
||||
*
|
||||
* @return List[Pet]
|
||||
*/
|
||||
def findPetsByStatus(status : Seq[String]) : List[Pet]
|
||||
/** Finds Pets by tags
|
||||
*
|
||||
* @return List[Pet]
|
||||
*/
|
||||
def findPetsByTags(tags : Seq[String]) : List[Pet]
|
||||
/** Find pet by ID
|
||||
*
|
||||
* @return Pet
|
||||
*/
|
||||
def getPetById(petId : Long) : Pet
|
||||
/** Update an existing pet
|
||||
*
|
||||
* @return Pet
|
||||
*/
|
||||
def updatePet(pet : Pet) : Pet
|
||||
/** Updates a pet in the store with form data
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def updatePetWithForm(petId : Long, name : Option[String], status : Option[String]) : Unit
|
||||
/** uploads an image
|
||||
*
|
||||
* @return ApiResponse
|
||||
*/
|
||||
def uploadFile(petId : Long, additionalMetadata : Option[String], file : Option[File]) : ApiResponse
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this is generated from apiRoutes.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import sample.cask.model.*
|
||||
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
import sample.cask.model.Order
|
||||
|
||||
class StoreRoutes(service : StoreService) extends cask.Routes {
|
||||
|
||||
|
||||
/** Delete purchase order by ID
|
||||
*
|
||||
*/
|
||||
@cask.delete("/store/order/:orderId")
|
||||
def deleteOrder(orderId : String, request: cask.Request) = {
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
orderId <- Parsed(orderId)
|
||||
result <- Parsed.eval(service.deleteOrder(orderId))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Returns pet inventories by status
|
||||
*
|
||||
*/
|
||||
@cask.get("/store/inventory")
|
||||
def getInventory(request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
result <- Parsed.eval(service.getInventory())
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Find purchase order by ID
|
||||
*
|
||||
*/
|
||||
@cask.get("/store/order/:orderId")
|
||||
def getOrderById(orderId : Long, request: cask.Request) = {
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
orderId <- Parsed(orderId)
|
||||
result <- Parsed.eval(service.getOrderById(orderId))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Place an order for a pet
|
||||
*
|
||||
*/
|
||||
@cask.post("/store/order")
|
||||
def placeOrder(request: cask.Request) = {
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
orderData <- Parsed.eval(OrderData.fromJsonString(request.bodyAsString)).mapError(e => s"Error parsing json as Order from >${request.bodyAsString}< : ${e}") /* not array or map */
|
||||
order <- Parsed.fromTry(orderData.validated(failFast))
|
||||
result <- Parsed.eval(service.placeOrder(order))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
|
||||
initialize()
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// generated from apiService.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import _root_.sample.cask.model.Order
|
||||
|
||||
import _root_.sample.cask.model.*
|
||||
|
||||
object StoreService {
|
||||
def apply() : StoreService = new StoreService {
|
||||
override def deleteOrder(orderId : String) : Unit = ???
|
||||
override def getInventory() : Map[String, Int] = ???
|
||||
override def getOrderById(orderId : Long) : Order = ???
|
||||
override def placeOrder(order : Order) : Order = ???
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Store business-logic
|
||||
*/
|
||||
trait StoreService {
|
||||
/** Delete purchase order by ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def deleteOrder(orderId : String) : Unit
|
||||
/** Returns pet inventories by status
|
||||
*
|
||||
* @return Map[String, Int]
|
||||
*/
|
||||
def getInventory() : Map[String, Int]
|
||||
/** Find purchase order by ID
|
||||
*
|
||||
* @return Order
|
||||
*/
|
||||
def getOrderById(orderId : Long) : Order
|
||||
/** Place an order for a pet
|
||||
*
|
||||
* @return Order
|
||||
*/
|
||||
def placeOrder(order : Order) : Order
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// this is generated from apiRoutes.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import sample.cask.model.*
|
||||
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
import java.time.OffsetDateTime
|
||||
import sample.cask.model.User
|
||||
|
||||
class UserRoutes(service : UserService) extends cask.Routes {
|
||||
|
||||
// route group for routeWorkAroundForGETUser
|
||||
@cask.get("/user", true)
|
||||
def routeWorkAroundForGETUser(request: cask.Request,username : Option[String] = None,password : Option[String] = None) = {
|
||||
request.remainingPathSegments match {
|
||||
case Seq("login") => loginUser(request,username.getOrElse(""), password.getOrElse(""))
|
||||
case Seq("logout") => logoutUser(request)
|
||||
case Seq(username) => getUserByName(username,request)
|
||||
case _ => cask.Response("Not Found", statusCode = 404)
|
||||
}
|
||||
}
|
||||
|
||||
/** Create user
|
||||
*
|
||||
*/
|
||||
@cask.post("/user")
|
||||
def createUser(request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
userData <- Parsed.eval(UserData.fromJsonString(request.bodyAsString)).mapError(e => s"Error parsing json as User from >${request.bodyAsString}< : ${e}") /* not array or map */
|
||||
user <- Parsed.fromTry(userData.validated(failFast))
|
||||
result <- Parsed.eval(service.createUser(user))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Creates list of users with given input array
|
||||
*
|
||||
*/
|
||||
@cask.post("/user/createWithArray")
|
||||
def createUsersWithArrayInput(request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
user <- Parsed.fromTry(UserData.manyFromJsonStringValidated(request.bodyAsString)).mapError(e => s"Error parsing json as an array of User from >${request.bodyAsString}< : ${e}") /* array */
|
||||
result <- Parsed.eval(service.createUsersWithArrayInput(user))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Creates list of users with given input array
|
||||
*
|
||||
*/
|
||||
@cask.post("/user/createWithList")
|
||||
def createUsersWithListInput(request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
user <- Parsed.fromTry(UserData.manyFromJsonStringValidated(request.bodyAsString)).mapError(e => s"Error parsing json as an array of User from >${request.bodyAsString}< : ${e}") /* array */
|
||||
result <- Parsed.eval(service.createUsersWithListInput(user))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Delete user
|
||||
*
|
||||
*/
|
||||
@cask.delete("/user/:username")
|
||||
def deleteUser(username : String, request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
username <- Parsed(username)
|
||||
result <- Parsed.eval(service.deleteUser(username))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Get user by user name
|
||||
*
|
||||
*/
|
||||
// conflicts with [/user/{username}, /user/login, /user/logout] after/user, ignoring @cask.get("/user/:username")
|
||||
def getUserByName(username : String, request: cask.Request) = {
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
username <- Parsed(username)
|
||||
result <- Parsed.eval(service.getUserByName(username))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Logs user into the system
|
||||
*
|
||||
*/
|
||||
// conflicts with [/user/{username}, /user/login, /user/logout] after/user, ignoring @cask.get("/user/login")
|
||||
def loginUser(request: cask.Request, username : String, password : String) = {
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
result <- Parsed.eval(service.loginUser(username, password))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Logs out current logged in user session
|
||||
*
|
||||
*/
|
||||
// conflicts with [/user/{username}, /user/login, /user/logout] after/user, ignoring @cask.get("/user/logout")
|
||||
def logoutUser(request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
result <- Parsed.eval(service.logoutUser())
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
/** Updated user
|
||||
*
|
||||
*/
|
||||
@cask.put("/user/:username")
|
||||
def updateUser(username : String, request: cask.Request) = {
|
||||
// auth method api_key : apiKey, keyParamName: api_key
|
||||
|
||||
def failFast = request.queryParams.keySet.contains("failFast")
|
||||
|
||||
val result = for {
|
||||
username <- Parsed(username)
|
||||
userData <- Parsed.eval(UserData.fromJsonString(request.bodyAsString)).mapError(e => s"Error parsing json as User from >${request.bodyAsString}< : ${e}") /* not array or map */
|
||||
user <- Parsed.fromTry(userData.validated(failFast))
|
||||
result <- Parsed.eval(service.updateUser(username, user))
|
||||
} yield result
|
||||
|
||||
result match {
|
||||
case Left(error) => cask.Response(error, 500)
|
||||
case Right(_) => cask.Response("", 200)
|
||||
}
|
||||
}
|
||||
|
||||
initialize()
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//> using scala "3.3.1"
|
||||
//> using lib "com.lihaoyi::cask:0.8.3"
|
||||
//> using lib "com.lihaoyi::scalatags:0.12.0"
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
// generated from apiService.mustache
|
||||
package sample.cask.api
|
||||
|
||||
import _root_.java.time.OffsetDateTime
|
||||
import _root_.sample.cask.model.User
|
||||
|
||||
import _root_.sample.cask.model.*
|
||||
|
||||
object UserService {
|
||||
def apply() : UserService = new UserService {
|
||||
override def createUser(user : User) : Unit = ???
|
||||
override def createUsersWithArrayInput(user : Seq[User]) : Unit = ???
|
||||
override def createUsersWithListInput(user : Seq[User]) : Unit = ???
|
||||
override def deleteUser(username : String) : Unit = ???
|
||||
override def getUserByName(username : String) : User = ???
|
||||
override def loginUser(username : String, password : String) : String = ???
|
||||
override def logoutUser() : Unit = ???
|
||||
override def updateUser(username : String, user : User) : Unit = ???
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The User business-logic
|
||||
*/
|
||||
trait UserService {
|
||||
/** Create user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def createUser(user : User) : Unit
|
||||
/** Creates list of users with given input array
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def createUsersWithArrayInput(user : Seq[User]) : Unit
|
||||
/** Creates list of users with given input array
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def createUsersWithListInput(user : Seq[User]) : Unit
|
||||
/** Delete user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def deleteUser(username : String) : Unit
|
||||
/** Get user by user name
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
def getUserByName(username : String) : User
|
||||
/** Logs user into the system
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
def loginUser(username : String, password : String) : String
|
||||
/** Logs out current logged in user session
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def logoutUser() : Unit
|
||||
/** Updated user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def updateUser(username : String, user : User) : Unit
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
package sample.cask.api
|
||||
|
||||
|
||||
import cask.FormEntry
|
||||
import io.undertow.server.handlers.form.{FormData, FormParserFactory}
|
||||
|
||||
import java.io.File
|
||||
import scala.jdk.CollectionConverters.*
|
||||
import java.time.LocalDate
|
||||
import java.util.UUID
|
||||
import scala.reflect.ClassTag
|
||||
import scala.util.*
|
||||
|
||||
// needed for BigDecimal params
|
||||
given cask.endpoints.QueryParamReader.SimpleParam[BigDecimal](BigDecimal.apply)
|
||||
|
||||
// a parsed value from an HTTP request
|
||||
opaque type Parsed[A] = Either[String, A]
|
||||
|
||||
object Parsed {
|
||||
def apply[A](value: A): Parsed[A] = Right(value)
|
||||
|
||||
def eval[A](value: => A): Parsed[A] = Try(value) match {
|
||||
case Failure(exp) => Left(s"Error: ${exp.getMessage}")
|
||||
case Success(ok) => Right(ok)
|
||||
}
|
||||
|
||||
def fromTry[A](value : Try[A]) = value match {
|
||||
case Failure(err) => Left(err.getMessage)
|
||||
case Success(ok) => Right(ok)
|
||||
}
|
||||
|
||||
def fail[A](msg: String): Parsed[A] = Left(msg)
|
||||
|
||||
def optionalValue(map: Map[String, collection.Seq[String]], key: String): Parsed[Option[String]] = {
|
||||
map.get(key) match {
|
||||
case Some(Seq(only: String)) => Parsed(Option(only))
|
||||
case Some(Seq()) => Parsed(None)
|
||||
case Some(many) => Parsed.fail(s"${many.size} values set for '$key'")
|
||||
case None => Parsed(None)
|
||||
}
|
||||
}
|
||||
|
||||
def singleValue(map: Map[String, collection.Seq[String]], key : String): Parsed[String] = {
|
||||
map.get(key) match {
|
||||
case Some(Seq(only : String)) => Parsed(only)
|
||||
case Some(Seq()) => Parsed("")
|
||||
case Some(many) => Parsed.fail(s"${many.size} values set for '$key'")
|
||||
case None => Parsed.fail(s"required '$key' was not set")
|
||||
}
|
||||
}
|
||||
|
||||
def manyValues(map: Map[String, collection.Seq[String]], key : String, required: Boolean): Parsed[List[String]] = {
|
||||
map.get(key) match {
|
||||
case Some(many) => Parsed(many.toList)
|
||||
case None if required => Parsed.fail(s"required '$key' was not set")
|
||||
case None => Parsed(Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension[A] (parsed: Parsed[A]) {
|
||||
def toEither: Either[String, A] = parsed
|
||||
|
||||
def asLong(using ev : A =:= String): Parsed[Long] = as[Long](_.toLongOption)
|
||||
def asBoolean(using ev : A =:= String): Parsed[Boolean] = as[Boolean](_.toBooleanOption)
|
||||
def asInt(using ev : A =:= String): Parsed[Int] = as[Int](_.toIntOption)
|
||||
def asByte(using ev : A =:= String): Parsed[Byte] = as[Byte](_.toByteOption)
|
||||
def asUuid(using ev : A =:= String): Parsed[UUID] = as[UUID](x => Try(UUID.fromString(x)).toOption)
|
||||
def asFloat(using ev : A =:= String): Parsed[Float] = as[Float](_.toFloatOption)
|
||||
def asDouble(using ev : A =:= String): Parsed[Double] = as[Double](_.toDoubleOption)
|
||||
def asDate(using ev: A =:= String): Parsed[LocalDate] = as[LocalDate](x => Try(LocalDate.parse(x)).toOption)
|
||||
|
||||
private def as[B : ClassTag](f : String => Option[B])(using ev : A =:= String): Parsed[B] = parsed.flatMap { str =>
|
||||
f(ev(str)) match {
|
||||
case None => Parsed.fail(s"'$str' cannot be parsed as a ${implicitly[ClassTag[B]].runtimeClass}")
|
||||
case Some(x) => Parsed(x)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def mapError(f : String => String) : Parsed[A] = parsed match {
|
||||
case Left(msg) => Left(f(msg))
|
||||
case right => right
|
||||
}
|
||||
|
||||
def map[B](f: A => B): Parsed[B] = parsed match {
|
||||
case Right(value) => Right(f(value))
|
||||
case Left(err) => Left(err)
|
||||
}
|
||||
def flatMap[B](f : A => Parsed[B]): Parsed[B] = parsed match {
|
||||
case Right(value) => f(value)
|
||||
case Left(err) => Left(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension (request: cask.Request) {
|
||||
|
||||
def formSingleValueRequired(paramName: String): Parsed[String] = {
|
||||
val data = formDataForKey(paramName).map(_.getValue).toSeq
|
||||
Parsed.singleValue(Map(paramName -> data), paramName)
|
||||
}
|
||||
def formSingleValueOptional(paramName: String): Parsed[Option[String]] = {
|
||||
val data = formDataForKey(paramName).map(_.getValue).toSeq
|
||||
Parsed.optionalValue(Map(paramName -> data), paramName)
|
||||
}
|
||||
|
||||
def formValueAsFileOptional(paramName: String): Parsed[Option[File]] = {
|
||||
val data = formDataForKey(paramName)
|
||||
data.map(_.getFileItem.getFile.toFile).toSeq match {
|
||||
case Seq() => Parsed(None)
|
||||
case Seq(file) => Parsed(Option(file))
|
||||
case many => Parsed.fail(s"${many.size} file values set for '$paramName'")
|
||||
}
|
||||
}
|
||||
|
||||
def formValueAsFileRequired(paramName: String): Parsed[File] = {
|
||||
val data = formDataForKey(paramName)
|
||||
data.map(_.getFileItem.getFile.toFile).toSeq match {
|
||||
case Seq() => Parsed.fail(s"No file form data was submitted for '$paramName'. The submitted form keys were: ${formDataKeys.mkString(",")}")
|
||||
case Seq(file) => Parsed(file)
|
||||
case many => Parsed.fail(s"${many.size} file values set for '$paramName'")
|
||||
}
|
||||
}
|
||||
|
||||
def formManyValues(paramName: String, required: Boolean): Parsed[List[String]] = {
|
||||
val data = formDataForKey(paramName).map(_.getValue).toSeq
|
||||
Parsed.manyValues(Map(paramName -> data), paramName, required)
|
||||
}
|
||||
|
||||
def formData: FormData = FormParserFactory.builder().build().createParser(request.exchange).parseBlocking()
|
||||
|
||||
def formDataKeys: Iterator[String] = formData.iterator().asScala
|
||||
|
||||
def formDataForKey(paramName: String): Iterable[FormData.FormValue] = formData.get(paramName).asScala
|
||||
|
||||
def headerSingleValueOptional(paramName: String): Parsed[Option[String]] = Parsed.optionalValue(request.headers, paramName)
|
||||
def headerSingleValueRequired(paramName: String): Parsed[String] = Parsed.singleValue(request.headers, paramName)
|
||||
|
||||
def headerManyValues(paramName: String, required: Boolean): Parsed[List[String]] = Parsed.manyValues(request.headers, paramName, required)
|
||||
|
||||
def bodyAsString = new String(request.readAllBytes(), "UTF-8")
|
||||
|
||||
def pathValue(index: Int, paramName: String, required : Boolean): Parsed[String] = {
|
||||
request
|
||||
.remainingPathSegments
|
||||
.lift(index) match {
|
||||
case Some(value) => Right(value)
|
||||
case None if required => Left(s"'$paramName'' is a required path parameter at path position $index")
|
||||
case None => Right("")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
case class ApiResponse(
|
||||
code: Option[Int] = None ,
|
||||
|
||||
`type`: Option[String] = None ,
|
||||
|
||||
message: Option[String] = None
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = asData.asJson
|
||||
|
||||
def asData : ApiResponseData = {
|
||||
ApiResponseData(
|
||||
code = code.getOrElse(0),
|
||||
`type` = `type`.getOrElse(""),
|
||||
message = message.getOrElse("")
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object ApiResponse{
|
||||
|
||||
given RW[ApiResponse] = ApiResponseData.readWriter.bimap[ApiResponse](_.asData, _.asModel)
|
||||
|
||||
enum Fields(fieldName : String) extends Field(fieldName) {
|
||||
case code extends Fields("code")
|
||||
case `type` extends Fields("`type`")
|
||||
case message extends Fields("message")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
/** ApiResponseData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class ApiResponseData(
|
||||
code: Int = 0 ,
|
||||
|
||||
`type`: String = "" ,
|
||||
|
||||
message: String = ""
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = write(this)
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ==================
|
||||
// code
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// `type`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
}
|
||||
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[ApiResponse] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : ApiResponse = {
|
||||
ApiResponse(
|
||||
code = Option(
|
||||
code
|
||||
)
|
||||
,
|
||||
`type` = Option(
|
||||
`type`
|
||||
)
|
||||
,
|
||||
message = Option(
|
||||
message
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ApiResponseData {
|
||||
|
||||
given readWriter : RW[ApiResponseData] = macroRW
|
||||
|
||||
def fromJsonString(jason : String) : ApiResponseData = try {
|
||||
read[ApiResponseData](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[ApiResponseData] = try {
|
||||
read[List[ApiResponseData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[ApiResponse]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[ApiResponse]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, ApiResponseData] = try {
|
||||
read[Map[String, ApiResponseData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, ApiResponse]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, ApiResponse]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
case class Category(
|
||||
id: Option[Long] = None ,
|
||||
|
||||
name: Option[String] = None
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = asData.asJson
|
||||
|
||||
def asData : CategoryData = {
|
||||
CategoryData(
|
||||
id = id.getOrElse(0),
|
||||
name = name.getOrElse("")
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object Category{
|
||||
|
||||
given RW[Category] = CategoryData.readWriter.bimap[Category](_.asData, _.asModel)
|
||||
|
||||
enum Fields(fieldName : String) extends Field(fieldName) {
|
||||
case id extends Fields("id")
|
||||
case name extends Fields("name")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
/** CategoryData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class CategoryData(
|
||||
id: Long = 0 ,
|
||||
|
||||
name: String = ""
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = write(this)
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ==================
|
||||
// id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// name
|
||||
// validate against pattern '^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$'
|
||||
if (errors.isEmpty || !failFast) {
|
||||
val regex = """^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$"""
|
||||
if name == null || !regex.r.matches(name) then
|
||||
errors += ValidationError(path :+ Category.Fields.name, s"value '$name' doesn't match pattern $regex")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
}
|
||||
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[Category] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : Category = {
|
||||
Category(
|
||||
id = Option(
|
||||
id
|
||||
)
|
||||
,
|
||||
name = Option(
|
||||
name
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object CategoryData {
|
||||
|
||||
given readWriter : RW[CategoryData] = macroRW
|
||||
|
||||
def fromJsonString(jason : String) : CategoryData = try {
|
||||
read[CategoryData](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[CategoryData] = try {
|
||||
read[List[CategoryData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[Category]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[Category]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, CategoryData] = try {
|
||||
read[Map[String, CategoryData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, Category]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, Category]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
case class Order(
|
||||
id: Option[Long] = None ,
|
||||
|
||||
petId: Option[Long] = None ,
|
||||
|
||||
quantity: Option[Int] = None ,
|
||||
|
||||
shipDate: Option[OffsetDateTime] = None ,
|
||||
|
||||
/* Order Status */
|
||||
status: Option[Order.StatusEnum] = None ,
|
||||
|
||||
complete: Option[Boolean] = None
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = asData.asJson
|
||||
|
||||
def asData : OrderData = {
|
||||
OrderData(
|
||||
id = id.getOrElse(0),
|
||||
petId = petId.getOrElse(0),
|
||||
quantity = quantity.getOrElse(0),
|
||||
shipDate = shipDate.getOrElse(null),
|
||||
status = status.getOrElse(null),
|
||||
complete = complete.getOrElse(false)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object Order{
|
||||
|
||||
given RW[Order] = OrderData.readWriter.bimap[Order](_.asData, _.asModel)
|
||||
|
||||
enum Fields(fieldName : String) extends Field(fieldName) {
|
||||
case id extends Fields("id")
|
||||
case petId extends Fields("petId")
|
||||
case quantity extends Fields("quantity")
|
||||
case shipDate extends Fields("shipDate")
|
||||
case status extends Fields("status")
|
||||
case complete extends Fields("complete")
|
||||
}
|
||||
|
||||
// baseName=status
|
||||
// nameInCamelCase = status
|
||||
enum StatusEnum derives ReadWriter {
|
||||
case placed
|
||||
case approved
|
||||
case delivered
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
/** OrderData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class OrderData(
|
||||
id: Long = 0 ,
|
||||
|
||||
petId: Long = 0 ,
|
||||
|
||||
quantity: Int = 0 ,
|
||||
|
||||
shipDate: OffsetDateTime = null ,
|
||||
|
||||
/* Order Status */
|
||||
status: Order.StatusEnum = null ,
|
||||
|
||||
complete: Boolean = false
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = write(this)
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ==================
|
||||
// id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// petId
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// quantity
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// shipDate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// status
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// complete
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
}
|
||||
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[Order] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : Order = {
|
||||
Order(
|
||||
id = Option(
|
||||
id
|
||||
)
|
||||
,
|
||||
petId = Option(
|
||||
petId
|
||||
)
|
||||
,
|
||||
quantity = Option(
|
||||
quantity
|
||||
)
|
||||
,
|
||||
shipDate = Option(
|
||||
shipDate
|
||||
)
|
||||
,
|
||||
status = Option(
|
||||
status
|
||||
)
|
||||
,
|
||||
complete = Option(
|
||||
complete
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object OrderData {
|
||||
|
||||
given readWriter : RW[OrderData] = macroRW
|
||||
|
||||
def fromJsonString(jason : String) : OrderData = try {
|
||||
read[OrderData](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[OrderData] = try {
|
||||
read[List[OrderData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[Order]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[Order]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, OrderData] = try {
|
||||
read[Map[String, OrderData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, Order]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, Order]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import sample.cask.model.Category
|
||||
import sample.cask.model.Tag
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
case class Pet(
|
||||
id: Option[Long] = None ,
|
||||
|
||||
category: Option[Category] = None ,
|
||||
|
||||
name: String,
|
||||
|
||||
photoUrls: Seq[String],
|
||||
|
||||
tags: Seq[Tag] = Nil ,
|
||||
|
||||
/* pet status in the store */
|
||||
status: Option[Pet.StatusEnum] = None
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = asData.asJson
|
||||
|
||||
def asData : PetData = {
|
||||
PetData(
|
||||
id = id.getOrElse(0),
|
||||
category = category.map(_.asData).getOrElse(null),
|
||||
name = name,
|
||||
photoUrls = photoUrls,
|
||||
tags = tags.map(_.asData),
|
||||
status = status.getOrElse(null)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object Pet{
|
||||
|
||||
given RW[Pet] = PetData.readWriter.bimap[Pet](_.asData, _.asModel)
|
||||
|
||||
enum Fields(fieldName : String) extends Field(fieldName) {
|
||||
case id extends Fields("id")
|
||||
case category extends Fields("category")
|
||||
case name extends Fields("name")
|
||||
case photoUrls extends Fields("photoUrls")
|
||||
case tags extends Fields("tags")
|
||||
case status extends Fields("status")
|
||||
}
|
||||
|
||||
// baseName=status
|
||||
// nameInCamelCase = status
|
||||
enum StatusEnum derives ReadWriter {
|
||||
case available
|
||||
case pending
|
||||
case sold
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import sample.cask.model.Category
|
||||
import sample.cask.model.Tag
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
/** PetData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class PetData(
|
||||
id: Long = 0 ,
|
||||
|
||||
category: CategoryData = null ,
|
||||
|
||||
name: String,
|
||||
|
||||
photoUrls: Seq[String],
|
||||
|
||||
tags: Seq[TagData] = Nil ,
|
||||
|
||||
/* pet status in the store */
|
||||
status: Pet.StatusEnum = null
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = write(this)
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ==================
|
||||
// id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// category
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// validating category
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if category != null then errors ++= category.validationErrors(path :+ Pet.Fields.category, failFast)
|
||||
}
|
||||
|
||||
// ==================
|
||||
// name
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// photoUrls
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// tags
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (errors.isEmpty || !failFast) {
|
||||
if (tags != null) {
|
||||
tags.zipWithIndex.foreach {
|
||||
case (value, i) if errors.isEmpty || !failFast =>
|
||||
errors ++= value.validationErrors(
|
||||
path :+ Pet.Fields.tags :+ Field(i.toString),
|
||||
failFast)
|
||||
case (value, i) =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================
|
||||
// status
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
}
|
||||
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[Pet] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : Pet = {
|
||||
Pet(
|
||||
id = Option(
|
||||
id
|
||||
)
|
||||
,
|
||||
category = Option(
|
||||
category
|
||||
)
|
||||
.map(_.asModel),
|
||||
name =
|
||||
name
|
||||
|
||||
,
|
||||
photoUrls =
|
||||
photoUrls
|
||||
|
||||
,
|
||||
tags =
|
||||
tags
|
||||
|
||||
.map(_.asModel),
|
||||
status = Option(
|
||||
status
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object PetData {
|
||||
|
||||
given readWriter : RW[PetData] = macroRW
|
||||
|
||||
def fromJsonString(jason : String) : PetData = try {
|
||||
read[PetData](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[PetData] = try {
|
||||
read[List[PetData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[Pet]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[Pet]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, PetData] = try {
|
||||
read[Map[String, PetData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, Pet]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, Pet]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
case class Tag(
|
||||
id: Option[Long] = None ,
|
||||
|
||||
name: Option[String] = None
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = asData.asJson
|
||||
|
||||
def asData : TagData = {
|
||||
TagData(
|
||||
id = id.getOrElse(0),
|
||||
name = name.getOrElse("")
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object Tag{
|
||||
|
||||
given RW[Tag] = TagData.readWriter.bimap[Tag](_.asData, _.asModel)
|
||||
|
||||
enum Fields(fieldName : String) extends Field(fieldName) {
|
||||
case id extends Fields("id")
|
||||
case name extends Fields("name")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
/** TagData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class TagData(
|
||||
id: Long = 0 ,
|
||||
|
||||
name: String = ""
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = write(this)
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ==================
|
||||
// id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// name
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
}
|
||||
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[Tag] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : Tag = {
|
||||
Tag(
|
||||
id = Option(
|
||||
id
|
||||
)
|
||||
,
|
||||
name = Option(
|
||||
name
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object TagData {
|
||||
|
||||
given readWriter : RW[TagData] = macroRW
|
||||
|
||||
def fromJsonString(jason : String) : TagData = try {
|
||||
read[TagData](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[TagData] = try {
|
||||
read[List[TagData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[Tag]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[Tag]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, TagData] = try {
|
||||
read[Map[String, TagData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, Tag]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, Tag]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using model.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
case class User(
|
||||
id: Option[Long] = None ,
|
||||
|
||||
username: Option[String] = None ,
|
||||
|
||||
firstName: Option[String] = None ,
|
||||
|
||||
lastName: Option[String] = None ,
|
||||
|
||||
email: Option[String] = None ,
|
||||
|
||||
password: Option[String] = None ,
|
||||
|
||||
phone: Option[String] = None ,
|
||||
|
||||
/* User Status */
|
||||
userStatus: Option[Int] = None
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = asData.asJson
|
||||
|
||||
def asData : UserData = {
|
||||
UserData(
|
||||
id = id.getOrElse(0),
|
||||
username = username.getOrElse(""),
|
||||
firstName = firstName.getOrElse(""),
|
||||
lastName = lastName.getOrElse(""),
|
||||
email = email.getOrElse(""),
|
||||
password = password.getOrElse(""),
|
||||
phone = phone.getOrElse(""),
|
||||
userStatus = userStatus.getOrElse(0)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object User{
|
||||
|
||||
given RW[User] = UserData.readWriter.bimap[User](_.asData, _.asModel)
|
||||
|
||||
enum Fields(fieldName : String) extends Field(fieldName) {
|
||||
case id extends Fields("id")
|
||||
case username extends Fields("username")
|
||||
case firstName extends Fields("firstName")
|
||||
case lastName extends Fields("lastName")
|
||||
case email extends Fields("email")
|
||||
case password extends Fields("password")
|
||||
case phone extends Fields("phone")
|
||||
case userStatus extends Fields("userStatus")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
// this model was generated using modelData.mustache
|
||||
package sample.cask.model
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.*
|
||||
|
||||
// see https://com-lihaoyi.github.io/upickle/
|
||||
import upickle.default.{ReadWriter => RW, macroRW}
|
||||
import upickle.default.*
|
||||
|
||||
/** UserData a data transfer object, primarily for simple json serialisation.
|
||||
* It has no validation - there may be nulls, values out of range, etc
|
||||
*/
|
||||
case class UserData(
|
||||
id: Long = 0 ,
|
||||
|
||||
username: String = "" ,
|
||||
|
||||
firstName: String = "" ,
|
||||
|
||||
lastName: String = "" ,
|
||||
|
||||
email: String = "" ,
|
||||
|
||||
password: String = "" ,
|
||||
|
||||
phone: String = "" ,
|
||||
|
||||
/* User Status */
|
||||
userStatus: Int = 0
|
||||
|
||||
) {
|
||||
|
||||
def asJson: String = write(this)
|
||||
|
||||
def validationErrors(path : Seq[Field], failFast : Boolean) : Seq[ValidationError] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[ValidationError]()
|
||||
// ==================
|
||||
// id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// username
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// firstName
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// lastName
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// email
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// password
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// phone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// userStatus
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
errors.toSeq
|
||||
}
|
||||
|
||||
def validated(failFast : Boolean = false) : scala.util.Try[User] = {
|
||||
validationErrors(Vector(), failFast) match {
|
||||
case Seq() => Success(asModel)
|
||||
case first +: theRest => Failure(ValidationErrors(first, theRest))
|
||||
}
|
||||
}
|
||||
|
||||
/** use 'validated' to check validation */
|
||||
def asModel : User = {
|
||||
User(
|
||||
id = Option(
|
||||
id
|
||||
)
|
||||
,
|
||||
username = Option(
|
||||
username
|
||||
)
|
||||
,
|
||||
firstName = Option(
|
||||
firstName
|
||||
)
|
||||
,
|
||||
lastName = Option(
|
||||
lastName
|
||||
)
|
||||
,
|
||||
email = Option(
|
||||
email
|
||||
)
|
||||
,
|
||||
password = Option(
|
||||
password
|
||||
)
|
||||
,
|
||||
phone = Option(
|
||||
phone
|
||||
)
|
||||
,
|
||||
userStatus = Option(
|
||||
userStatus
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object UserData {
|
||||
|
||||
given readWriter : RW[UserData] = macroRW
|
||||
|
||||
def fromJsonString(jason : String) : UserData = try {
|
||||
read[UserData](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason': $e")
|
||||
}
|
||||
|
||||
def manyFromJsonString(jason : String) : Seq[UserData] = try {
|
||||
read[List[UserData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as list: $e")
|
||||
}
|
||||
|
||||
def manyFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Seq[User]] = {
|
||||
Try(manyFromJsonString(jason)).flatMap { list =>
|
||||
list.zipWithIndex.foldLeft(Try(Vector[User]())) {
|
||||
case (Success(list), (next, i)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(list :+ ok)
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $i: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def mapFromJsonString(jason : String) : Map[String, UserData] = try {
|
||||
read[Map[String, UserData]](jason)
|
||||
} catch {
|
||||
case NonFatal(e) => sys.error(s"Error parsing json '$jason' as map: $e")
|
||||
}
|
||||
|
||||
|
||||
def mapFromJsonStringValidated(jason : String, failFast : Boolean = false) : Try[Map[String, User]] = {
|
||||
Try(mapFromJsonString(jason)).flatMap { map =>
|
||||
map.foldLeft(Try(Map[String, User]())) {
|
||||
case (Success(map), (key, next)) =>
|
||||
next.validated(failFast) match {
|
||||
case Success(ok) => Success(map.updated(key, ok))
|
||||
case Failure(err) => Failure(new Exception(s"Validation error on element $key: ${err.getMessage}", err))
|
||||
}
|
||||
case (fail, _) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
package sample.cask.model
|
||||
|
||||
// model package
|
||||
import upickle.default._
|
||||
import java.time.*
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
/**
|
||||
* This base class lets us refer to fields in exceptions
|
||||
*/
|
||||
class Field(val name : String)
|
||||
|
||||
final case class ValidationErrors(
|
||||
first: ValidationError,
|
||||
remaining: Seq[ValidationError],
|
||||
message: String
|
||||
) extends Exception(message)
|
||||
|
||||
object ValidationErrors {
|
||||
def apply(first: ValidationError, remaining: Seq[ValidationError]) = {
|
||||
val noun = if remaining.isEmpty then "error" else "errors"
|
||||
new ValidationErrors(
|
||||
first,
|
||||
remaining,
|
||||
remaining.mkString(s"${remaining.size + 1} $noun found: ${first}", "\n\t", "")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final case class ValidationError(path : Seq[Field], message : String) extends Exception(message) {
|
||||
override def toString = s"ValidationError for ${path.mkString(".")}: $message"
|
||||
}
|
||||
|
||||
given ReadWriter[ZonedDateTime] = readwriter[String].bimap[ZonedDateTime](
|
||||
zonedDateTime => DateTimeFormatter.ISO_INSTANT.format(zonedDateTime),
|
||||
str => ZonedDateTime.parse(str, DateTimeFormatter.ISO_INSTANT))
|
||||
|
||||
given ReadWriter[LocalDateTime] = readwriter[String].bimap[LocalDateTime](
|
||||
zonedDateTime => DateTimeFormatter.ISO_INSTANT.format(zonedDateTime),
|
||||
str => LocalDateTime.parse(str, DateTimeFormatter.ISO_INSTANT))
|
||||
|
||||
given ReadWriter[LocalDate] = readwriter[String].bimap[LocalDate](
|
||||
zonedDateTime => DateTimeFormatter.ISO_INSTANT.format(zonedDateTime),
|
||||
str => LocalDate.parse(str, DateTimeFormatter.ISO_INSTANT))
|
||||
|
||||
given ReadWriter[OffsetDateTime] = readwriter[String].bimap[OffsetDateTime](
|
||||
zonedDateTime => DateTimeFormatter.ISO_INSTANT.format(zonedDateTime),
|
||||
str => scala.util.Try(OffsetDateTime.parse(str, DateTimeFormatter.ISO_DATE_TIME)).getOrElse(
|
||||
OffsetDateTime.parse(str, DateTimeFormatter.ISO_INSTANT)
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator.
|
||||
*
|
||||
* https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
package cask.groupId.server
|
||||
|
||||
def box(str: String): String = {
|
||||
val lines = str.linesIterator.toList
|
||||
val maxLen = (0 +: lines.map(_.length)).max
|
||||
val boxed = lines.map { line =>
|
||||
s" | ${line.padTo(maxLen, ' ')} |"
|
||||
}
|
||||
val bar = " +-" + ("-" * maxLen) + "-+"
|
||||
(bar +: boxed :+ bar).mkString("\n")
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class ApiResponseTest extends AnyWordSpec with Matchers {
|
||||
|
||||
"ApiResponse.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(ApiResponseData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val Failure(err : ValidationErrors) = ApiResponseData.fromJsonString("""""").validated()
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class CategoryTest extends AnyWordSpec with Matchers {
|
||||
|
||||
"Category.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(CategoryData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val Failure(err : ValidationErrors) = CategoryData.fromJsonString("""""").validated()
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class OrderTest extends AnyWordSpec with Matchers {
|
||||
|
||||
"Order.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(OrderData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val Failure(err : ValidationErrors) = OrderData.fromJsonString("""""").validated()
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
import sample.cask.model.Category
|
||||
import sample.cask.model.Tag
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class PetTest extends AnyWordSpec with Matchers {
|
||||
|
||||
"Pet.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(PetData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val Failure(err : ValidationErrors) = PetData.fromJsonString("""""").validated()
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class TagTest extends AnyWordSpec with Matchers {
|
||||
|
||||
"Tag.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(TagData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val Failure(err : ValidationErrors) = TagData.fromJsonString("""""").validated()
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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
|
||||
* Contact: team@openapitools.org
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
// this model was generated using modelTest.mustache
|
||||
package sample.cask.model
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
import scala.util.*
|
||||
|
||||
class UserTest extends AnyWordSpec with Matchers {
|
||||
|
||||
"User.fromJson" should {
|
||||
"""not parse invalid json""" in {
|
||||
val Failure(err) = Try(UserData.fromJsonString("invalid jason"))
|
||||
err.getMessage should startWith ("Error parsing json 'invalid jason'")
|
||||
}
|
||||
"""parse """ ignore {
|
||||
val Failure(err : ValidationErrors) = UserData.fromJsonString("""""").validated()
|
||||
|
||||
sys.error("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user