diff --git a/.openapi-generator-ignore b/.openapi-generator-ignore
new file mode 100644
index 0000000..1888593
--- /dev/null
+++ b/.openapi-generator-ignore
@@ -0,0 +1,28 @@
+# 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
+
+**/**
+
+!src/main/kotlin/org/trackedout/client/**
+!docs/
diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES
new file mode 100644
index 0000000..2723b1b
--- /dev/null
+++ b/.openapi-generator/FILES
@@ -0,0 +1,49 @@
+docs/AuthApi.md
+docs/AuthForgotPasswordPostRequest.md
+docs/AuthLoginPostRequest.md
+docs/AuthLogoutPostRequest.md
+docs/AuthRegisterPost201Response.md
+docs/AuthRegisterPostRequest.md
+docs/AuthResetPasswordPostRequest.md
+docs/AuthTokens.md
+docs/Error.md
+docs/Token.md
+docs/User.md
+docs/UserWithTokens.md
+docs/UsersApi.md
+docs/UsersGet200Response.md
+docs/UsersIdPatchRequest.md
+docs/UsersPostRequest.md
+src/main/kotlin/org/trackedout/client/apis/AuthApi.kt
+src/main/kotlin/org/trackedout/client/apis/UsersApi.kt
+src/main/kotlin/org/trackedout/client/infrastructure/ApiAbstractions.kt
+src/main/kotlin/org/trackedout/client/infrastructure/ApiClient.kt
+src/main/kotlin/org/trackedout/client/infrastructure/ApiResponse.kt
+src/main/kotlin/org/trackedout/client/infrastructure/BigDecimalAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/BigIntegerAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/ByteArrayAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/Errors.kt
+src/main/kotlin/org/trackedout/client/infrastructure/LocalDateAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/LocalDateTimeAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/OffsetDateTimeAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/PartConfig.kt
+src/main/kotlin/org/trackedout/client/infrastructure/RequestConfig.kt
+src/main/kotlin/org/trackedout/client/infrastructure/RequestMethod.kt
+src/main/kotlin/org/trackedout/client/infrastructure/ResponseExtensions.kt
+src/main/kotlin/org/trackedout/client/infrastructure/Serializer.kt
+src/main/kotlin/org/trackedout/client/infrastructure/URIAdapter.kt
+src/main/kotlin/org/trackedout/client/infrastructure/UUIDAdapter.kt
+src/main/kotlin/org/trackedout/client/models/AuthForgotPasswordPostRequest.kt
+src/main/kotlin/org/trackedout/client/models/AuthLoginPostRequest.kt
+src/main/kotlin/org/trackedout/client/models/AuthLogoutPostRequest.kt
+src/main/kotlin/org/trackedout/client/models/AuthRegisterPost201Response.kt
+src/main/kotlin/org/trackedout/client/models/AuthRegisterPostRequest.kt
+src/main/kotlin/org/trackedout/client/models/AuthResetPasswordPostRequest.kt
+src/main/kotlin/org/trackedout/client/models/AuthTokens.kt
+src/main/kotlin/org/trackedout/client/models/Error.kt
+src/main/kotlin/org/trackedout/client/models/Token.kt
+src/main/kotlin/org/trackedout/client/models/User.kt
+src/main/kotlin/org/trackedout/client/models/UserWithTokens.kt
+src/main/kotlin/org/trackedout/client/models/UsersGet200Response.kt
+src/main/kotlin/org/trackedout/client/models/UsersIdPatchRequest.kt
+src/main/kotlin/org/trackedout/client/models/UsersPostRequest.kt
diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION
new file mode 100644
index 0000000..3769235
--- /dev/null
+++ b/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.1.0
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 33d86e5..1f534f9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,6 +2,7 @@ plugins {
id 'fabric-loom' version '1.4-SNAPSHOT'
id 'maven-publish'
id "org.jetbrains.kotlin.jvm" version "1.9.21"
+ id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.19"
}
version = project.mod_version
@@ -44,6 +45,14 @@ dependencies {
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
+
+ // https://square.github.io/okhttp/#releases
+ implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0"))
+ // Define any required OkHttp artifacts without version
+ implementation("com.squareup.okhttp3:okhttp")
+ implementation("com.squareup.okhttp3:logging-interceptor")
+ implementation("com.squareup.moshi:moshi:1.14.0")
+ implementation("com.squareup.moshi:moshi-kotlin:1.14.0")
}
processResources {
diff --git a/docs/AuthApi.md b/docs/AuthApi.md
new file mode 100644
index 0000000..5aba7b4
--- /dev/null
+++ b/docs/AuthApi.md
@@ -0,0 +1,375 @@
+# AuthApi
+
+All URIs are relative to *http://localhost:3000/v1*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**authForgotPasswordPost**](AuthApi.md#authForgotPasswordPost) | **POST** /auth/forgot-password | Forgot password
+[**authLoginPost**](AuthApi.md#authLoginPost) | **POST** /auth/login | Login
+[**authLogoutPost**](AuthApi.md#authLogoutPost) | **POST** /auth/logout | Logout
+[**authRefreshTokensPost**](AuthApi.md#authRefreshTokensPost) | **POST** /auth/refresh-tokens | Refresh auth tokens
+[**authRegisterPost**](AuthApi.md#authRegisterPost) | **POST** /auth/register | Register as user
+[**authResetPasswordPost**](AuthApi.md#authResetPasswordPost) | **POST** /auth/reset-password | Reset password
+[**authSendVerificationEmailPost**](AuthApi.md#authSendVerificationEmailPost) | **POST** /auth/send-verification-email | Send verification email
+[**authVerifyEmailPost**](AuthApi.md#authVerifyEmailPost) | **POST** /auth/verify-email | verify email
+
+
+
+# **authForgotPasswordPost**
+> authForgotPasswordPost(authForgotPasswordPostRequest)
+
+Forgot password
+
+An email will be sent to reset password.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val authForgotPasswordPostRequest : AuthForgotPasswordPostRequest = // AuthForgotPasswordPostRequest |
+try {
+ apiInstance.authForgotPasswordPost(authForgotPasswordPostRequest)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authForgotPasswordPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authForgotPasswordPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **authForgotPasswordPostRequest** | [**AuthForgotPasswordPostRequest**](AuthForgotPasswordPostRequest.md)| |
+
+### Return type
+
+null (empty response body)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **authLoginPost**
+> AuthRegisterPost201Response authLoginPost(authLoginPostRequest)
+
+Login
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val authLoginPostRequest : AuthLoginPostRequest = // AuthLoginPostRequest |
+try {
+ val result : AuthRegisterPost201Response = apiInstance.authLoginPost(authLoginPostRequest)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authLoginPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authLoginPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **authLoginPostRequest** | [**AuthLoginPostRequest**](AuthLoginPostRequest.md)| |
+
+### Return type
+
+[**AuthRegisterPost201Response**](AuthRegisterPost201Response.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **authLogoutPost**
+> authLogoutPost(authLogoutPostRequest)
+
+Logout
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val authLogoutPostRequest : AuthLogoutPostRequest = // AuthLogoutPostRequest |
+try {
+ apiInstance.authLogoutPost(authLogoutPostRequest)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authLogoutPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authLogoutPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **authLogoutPostRequest** | [**AuthLogoutPostRequest**](AuthLogoutPostRequest.md)| |
+
+### Return type
+
+null (empty response body)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **authRefreshTokensPost**
+> UserWithTokens authRefreshTokensPost(authLogoutPostRequest)
+
+Refresh auth tokens
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val authLogoutPostRequest : AuthLogoutPostRequest = // AuthLogoutPostRequest |
+try {
+ val result : UserWithTokens = apiInstance.authRefreshTokensPost(authLogoutPostRequest)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authRefreshTokensPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authRefreshTokensPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **authLogoutPostRequest** | [**AuthLogoutPostRequest**](AuthLogoutPostRequest.md)| |
+
+### Return type
+
+[**UserWithTokens**](UserWithTokens.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **authRegisterPost**
+> AuthRegisterPost201Response authRegisterPost(authRegisterPostRequest)
+
+Register as user
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val authRegisterPostRequest : AuthRegisterPostRequest = // AuthRegisterPostRequest |
+try {
+ val result : AuthRegisterPost201Response = apiInstance.authRegisterPost(authRegisterPostRequest)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authRegisterPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authRegisterPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **authRegisterPostRequest** | [**AuthRegisterPostRequest**](AuthRegisterPostRequest.md)| |
+
+### Return type
+
+[**AuthRegisterPost201Response**](AuthRegisterPost201Response.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **authResetPasswordPost**
+> authResetPasswordPost(token, authResetPasswordPostRequest)
+
+Reset password
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val token : kotlin.String = token_example // kotlin.String | The reset password token
+val authResetPasswordPostRequest : AuthResetPasswordPostRequest = // AuthResetPasswordPostRequest |
+try {
+ apiInstance.authResetPasswordPost(token, authResetPasswordPostRequest)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authResetPasswordPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authResetPasswordPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **token** | **kotlin.String**| The reset password token |
+ **authResetPasswordPostRequest** | [**AuthResetPasswordPostRequest**](AuthResetPasswordPostRequest.md)| |
+
+### Return type
+
+null (empty response body)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **authSendVerificationEmailPost**
+> authSendVerificationEmailPost()
+
+Send verification email
+
+An email will be sent to verify email.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+try {
+ apiInstance.authSendVerificationEmailPost()
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authSendVerificationEmailPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authSendVerificationEmailPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+This endpoint does not need any parameter.
+
+### Return type
+
+null (empty response body)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+
+# **authVerifyEmailPost**
+> authVerifyEmailPost(token)
+
+verify email
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = AuthApi()
+val token : kotlin.String = token_example // kotlin.String | The verify email token
+try {
+ apiInstance.authVerifyEmailPost(token)
+} catch (e: ClientException) {
+ println("4xx response calling AuthApi#authVerifyEmailPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling AuthApi#authVerifyEmailPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **token** | **kotlin.String**| The verify email token |
+
+### Return type
+
+null (empty response body)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
diff --git a/docs/AuthForgotPasswordPostRequest.md b/docs/AuthForgotPasswordPostRequest.md
new file mode 100644
index 0000000..1554c60
--- /dev/null
+++ b/docs/AuthForgotPasswordPostRequest.md
@@ -0,0 +1,10 @@
+
+# AuthForgotPasswordPostRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**email** | **kotlin.String** | |
+
+
+
diff --git a/docs/AuthLoginPostRequest.md b/docs/AuthLoginPostRequest.md
new file mode 100644
index 0000000..175c800
--- /dev/null
+++ b/docs/AuthLoginPostRequest.md
@@ -0,0 +1,11 @@
+
+# AuthLoginPostRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**email** | **kotlin.String** | |
+**password** | **kotlin.String** | |
+
+
+
diff --git a/docs/AuthLogoutPostRequest.md b/docs/AuthLogoutPostRequest.md
new file mode 100644
index 0000000..fc22f2a
--- /dev/null
+++ b/docs/AuthLogoutPostRequest.md
@@ -0,0 +1,10 @@
+
+# AuthLogoutPostRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**refreshToken** | **kotlin.String** | |
+
+
+
diff --git a/docs/AuthRegisterPost201Response.md b/docs/AuthRegisterPost201Response.md
new file mode 100644
index 0000000..281c41f
--- /dev/null
+++ b/docs/AuthRegisterPost201Response.md
@@ -0,0 +1,11 @@
+
+# AuthRegisterPost201Response
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**user** | [**User**](User.md) | | [optional]
+**tokens** | [**AuthTokens**](AuthTokens.md) | | [optional]
+
+
+
diff --git a/docs/AuthRegisterPostRequest.md b/docs/AuthRegisterPostRequest.md
new file mode 100644
index 0000000..f7ef2f3
--- /dev/null
+++ b/docs/AuthRegisterPostRequest.md
@@ -0,0 +1,12 @@
+
+# AuthRegisterPostRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**name** | **kotlin.String** | |
+**email** | **kotlin.String** | must be unique |
+**password** | **kotlin.String** | At least one number and one letter |
+
+
+
diff --git a/docs/AuthResetPasswordPostRequest.md b/docs/AuthResetPasswordPostRequest.md
new file mode 100644
index 0000000..d83fd5b
--- /dev/null
+++ b/docs/AuthResetPasswordPostRequest.md
@@ -0,0 +1,10 @@
+
+# AuthResetPasswordPostRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**password** | **kotlin.String** | At least one number and one letter |
+
+
+
diff --git a/docs/AuthTokens.md b/docs/AuthTokens.md
new file mode 100644
index 0000000..b25938a
--- /dev/null
+++ b/docs/AuthTokens.md
@@ -0,0 +1,11 @@
+
+# AuthTokens
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**access** | [**Token**](Token.md) | | [optional]
+**refresh** | [**Token**](Token.md) | | [optional]
+
+
+
diff --git a/docs/Error.md b/docs/Error.md
new file mode 100644
index 0000000..6b0004f
--- /dev/null
+++ b/docs/Error.md
@@ -0,0 +1,11 @@
+
+# Error
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**code** | [**java.math.BigDecimal**](java.math.BigDecimal.md) | | [optional]
+**message** | **kotlin.String** | | [optional]
+
+
+
diff --git a/docs/Token.md b/docs/Token.md
new file mode 100644
index 0000000..0142d67
--- /dev/null
+++ b/docs/Token.md
@@ -0,0 +1,11 @@
+
+# Token
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**token** | **kotlin.String** | | [optional]
+**expires** | [**java.time.OffsetDateTime**](java.time.OffsetDateTime.md) | | [optional]
+
+
+
diff --git a/docs/User.md b/docs/User.md
new file mode 100644
index 0000000..bcc491f
--- /dev/null
+++ b/docs/User.md
@@ -0,0 +1,20 @@
+
+# User
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**id** | **kotlin.String** | | [optional]
+**email** | **kotlin.String** | | [optional]
+**name** | **kotlin.String** | | [optional]
+**role** | [**inline**](#Role) | | [optional]
+
+
+
+## Enum: role
+Name | Value
+---- | -----
+role | user, admin
+
+
+
diff --git a/docs/UserWithTokens.md b/docs/UserWithTokens.md
new file mode 100644
index 0000000..c87f980
--- /dev/null
+++ b/docs/UserWithTokens.md
@@ -0,0 +1,11 @@
+
+# UserWithTokens
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**user** | [**User**](User.md) | | [optional]
+**tokens** | [**AuthTokens**](AuthTokens.md) | | [optional]
+
+
+
diff --git a/docs/UsersApi.md b/docs/UsersApi.md
new file mode 100644
index 0000000..25be305
--- /dev/null
+++ b/docs/UsersApi.md
@@ -0,0 +1,269 @@
+# UsersApi
+
+All URIs are relative to *http://localhost:3000/v1*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**usersGet**](UsersApi.md#usersGet) | **GET** /users | Get all users
+[**usersIdDelete**](UsersApi.md#usersIdDelete) | **DELETE** /users/{id} | Delete a user
+[**usersIdGet**](UsersApi.md#usersIdGet) | **GET** /users/{id} | Get a user
+[**usersIdPatch**](UsersApi.md#usersIdPatch) | **PATCH** /users/{id} | Update a user
+[**usersPost**](UsersApi.md#usersPost) | **POST** /users | Create a user
+
+
+
+# **usersGet**
+> UsersGet200Response usersGet(name, role, sortBy, projectBy, limit, page)
+
+Get all users
+
+Only admins can retrieve all users.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = UsersApi()
+val name : kotlin.String = name_example // kotlin.String | User name
+val role : kotlin.String = role_example // kotlin.String | User role
+val sortBy : kotlin.String = sortBy_example // kotlin.String | sort by query in the form of field:desc/asc (ex. name:asc)
+val projectBy : kotlin.String = projectBy_example // kotlin.String | project by query in the form of field:hide/include (ex. name:hide)
+val limit : kotlin.Int = 56 // kotlin.Int | Maximum number of users
+val page : kotlin.Int = 56 // kotlin.Int | Page number
+try {
+ val result : UsersGet200Response = apiInstance.usersGet(name, role, sortBy, projectBy, limit, page)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling UsersApi#usersGet")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling UsersApi#usersGet")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **name** | **kotlin.String**| User name | [optional]
+ **role** | **kotlin.String**| User role | [optional]
+ **sortBy** | **kotlin.String**| sort by query in the form of field:desc/asc (ex. name:asc) | [optional]
+ **projectBy** | **kotlin.String**| project by query in the form of field:hide/include (ex. name:hide) | [optional]
+ **limit** | **kotlin.Int**| Maximum number of users | [optional]
+ **page** | **kotlin.Int**| Page number | [optional] [default to 1]
+
+### Return type
+
+[**UsersGet200Response**](UsersGet200Response.md)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+
+# **usersIdDelete**
+> usersIdDelete(id)
+
+Delete a user
+
+Logged in users can delete only themselves. Only admins can delete other users.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = UsersApi()
+val id : kotlin.String = id_example // kotlin.String | User id
+try {
+ apiInstance.usersIdDelete(id)
+} catch (e: ClientException) {
+ println("4xx response calling UsersApi#usersIdDelete")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling UsersApi#usersIdDelete")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **id** | **kotlin.String**| User id |
+
+### Return type
+
+null (empty response body)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+
+# **usersIdGet**
+> User usersIdGet(id)
+
+Get a user
+
+Logged in users can fetch only their own user information. Only admins can fetch other users.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = UsersApi()
+val id : kotlin.String = id_example // kotlin.String | User id
+try {
+ val result : User = apiInstance.usersIdGet(id)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling UsersApi#usersIdGet")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling UsersApi#usersIdGet")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **id** | **kotlin.String**| User id |
+
+### Return type
+
+[**User**](User.md)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+
+# **usersIdPatch**
+> User usersIdPatch(id, usersIdPatchRequest)
+
+Update a user
+
+Logged in users can only update their own information. Only admins can update other users.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = UsersApi()
+val id : kotlin.String = id_example // kotlin.String | User id
+val usersIdPatchRequest : UsersIdPatchRequest = // UsersIdPatchRequest |
+try {
+ val result : User = apiInstance.usersIdPatch(id, usersIdPatchRequest)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling UsersApi#usersIdPatch")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling UsersApi#usersIdPatch")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **id** | **kotlin.String**| User id |
+ **usersIdPatchRequest** | [**UsersIdPatchRequest**](UsersIdPatchRequest.md)| |
+
+### Return type
+
+[**User**](User.md)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+
+# **usersPost**
+> User usersPost(usersPostRequest)
+
+Create a user
+
+Only admins can create other users.
+
+### Example
+```kotlin
+// Import classes:
+//import org.trackedout.client.infrastructure.*
+//import org.trackedout.client.models.*
+
+val apiInstance = UsersApi()
+val usersPostRequest : UsersPostRequest = // UsersPostRequest |
+try {
+ val result : User = apiInstance.usersPost(usersPostRequest)
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling UsersApi#usersPost")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling UsersApi#usersPost")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **usersPostRequest** | [**UsersPostRequest**](UsersPostRequest.md)| |
+
+### Return type
+
+[**User**](User.md)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
diff --git a/docs/UsersGet200Response.md b/docs/UsersGet200Response.md
new file mode 100644
index 0000000..b601fab
--- /dev/null
+++ b/docs/UsersGet200Response.md
@@ -0,0 +1,14 @@
+
+# UsersGet200Response
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**results** | [**kotlin.collections.List<User>**](User.md) | | [optional]
+**page** | **kotlin.Int** | | [optional]
+**limit** | **kotlin.Int** | | [optional]
+**totalPages** | **kotlin.Int** | | [optional]
+**totalResults** | **kotlin.Int** | | [optional]
+
+
+
diff --git a/docs/UsersIdPatchRequest.md b/docs/UsersIdPatchRequest.md
new file mode 100644
index 0000000..7575289
--- /dev/null
+++ b/docs/UsersIdPatchRequest.md
@@ -0,0 +1,12 @@
+
+# UsersIdPatchRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**name** | **kotlin.String** | | [optional]
+**email** | **kotlin.String** | must be unique | [optional]
+**password** | **kotlin.String** | At least one number and one letter | [optional]
+
+
+
diff --git a/docs/UsersPostRequest.md b/docs/UsersPostRequest.md
new file mode 100644
index 0000000..e6f1e9f
--- /dev/null
+++ b/docs/UsersPostRequest.md
@@ -0,0 +1,20 @@
+
+# UsersPostRequest
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**name** | **kotlin.String** | |
+**email** | **kotlin.String** | must be unique |
+**password** | **kotlin.String** | At least one number and one letter |
+**role** | [**inline**](#Role) | |
+
+
+
+## Enum: role
+Name | Value
+---- | -----
+role | user, admin
+
+
+
diff --git a/openapi-config.yaml b/openapi-config.yaml
new file mode 100644
index 0000000..8593618
--- /dev/null
+++ b/openapi-config.yaml
@@ -0,0 +1 @@
+packageName: "org.trackedout.client"
diff --git a/src/main/kotlin/org/trackedout/AgroNet.kt b/src/main/kotlin/org/trackedout/AgroNet.kt
index 7c71278..15ddca9 100644
--- a/src/main/kotlin/org/trackedout/AgroNet.kt
+++ b/src/main/kotlin/org/trackedout/AgroNet.kt
@@ -38,6 +38,9 @@ object AgroNet : ModInitializer {
{ Text.literal("Processing /log-event { event=${event}, player=${player.name}, count=${count} }") },
true
)
+
+
+
1
})
)
diff --git a/src/main/kotlin/org/trackedout/client/apis/AuthApi.kt b/src/main/kotlin/org/trackedout/client/apis/AuthApi.kt
new file mode 100644
index 0000000..d136dbe
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/apis/AuthApi.kt
@@ -0,0 +1,628 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.apis
+
+import java.io.IOException
+import okhttp3.OkHttpClient
+import okhttp3.HttpUrl
+
+import org.trackedout.client.models.AuthForgotPasswordPostRequest
+import org.trackedout.client.models.AuthLoginPostRequest
+import org.trackedout.client.models.AuthLogoutPostRequest
+import org.trackedout.client.models.AuthRegisterPost201Response
+import org.trackedout.client.models.AuthRegisterPostRequest
+import org.trackedout.client.models.AuthResetPasswordPostRequest
+import org.trackedout.client.models.Error
+import org.trackedout.client.models.UserWithTokens
+
+import com.squareup.moshi.Json
+
+import org.trackedout.client.infrastructure.ApiClient
+import org.trackedout.client.infrastructure.ApiResponse
+import org.trackedout.client.infrastructure.ClientException
+import org.trackedout.client.infrastructure.ClientError
+import org.trackedout.client.infrastructure.ServerException
+import org.trackedout.client.infrastructure.ServerError
+import org.trackedout.client.infrastructure.MultiValueMap
+import org.trackedout.client.infrastructure.PartConfig
+import org.trackedout.client.infrastructure.RequestConfig
+import org.trackedout.client.infrastructure.RequestMethod
+import org.trackedout.client.infrastructure.ResponseType
+import org.trackedout.client.infrastructure.Success
+import org.trackedout.client.infrastructure.toMultiValue
+
+class AuthApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient = ApiClient.defaultClient) : ApiClient(basePath, client) {
+ companion object {
+ @JvmStatic
+ val defaultBasePath: String by lazy {
+ System.getProperties().getProperty(ApiClient.baseUrlKey, "http://localhost:3000/v1")
+ }
+ }
+
+ /**
+ * Forgot password
+ * An email will be sent to reset password.
+ * @param authForgotPasswordPostRequest
+ * @return void
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authForgotPasswordPost(authForgotPasswordPostRequest: AuthForgotPasswordPostRequest) : Unit {
+ val localVarResponse = authForgotPasswordPostWithHttpInfo(authForgotPasswordPostRequest = authForgotPasswordPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> Unit
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Forgot password
+ * An email will be sent to reset password.
+ * @param authForgotPasswordPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authForgotPasswordPostWithHttpInfo(authForgotPasswordPostRequest: AuthForgotPasswordPostRequest) : ApiResponse {
+ val localVariableConfig = authForgotPasswordPostRequestConfig(authForgotPasswordPostRequest = authForgotPasswordPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authForgotPasswordPost
+ *
+ * @param authForgotPasswordPostRequest
+ * @return RequestConfig
+ */
+ fun authForgotPasswordPostRequestConfig(authForgotPasswordPostRequest: AuthForgotPasswordPostRequest) : RequestConfig {
+ val localVariableBody = authForgotPasswordPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/forgot-password",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Login
+ *
+ * @param authLoginPostRequest
+ * @return AuthRegisterPost201Response
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authLoginPost(authLoginPostRequest: AuthLoginPostRequest) : AuthRegisterPost201Response {
+ val localVarResponse = authLoginPostWithHttpInfo(authLoginPostRequest = authLoginPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as AuthRegisterPost201Response
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Login
+ *
+ * @param authLoginPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authLoginPostWithHttpInfo(authLoginPostRequest: AuthLoginPostRequest) : ApiResponse {
+ val localVariableConfig = authLoginPostRequestConfig(authLoginPostRequest = authLoginPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authLoginPost
+ *
+ * @param authLoginPostRequest
+ * @return RequestConfig
+ */
+ fun authLoginPostRequestConfig(authLoginPostRequest: AuthLoginPostRequest) : RequestConfig {
+ val localVariableBody = authLoginPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/login",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Logout
+ *
+ * @param authLogoutPostRequest
+ * @return void
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authLogoutPost(authLogoutPostRequest: AuthLogoutPostRequest) : Unit {
+ val localVarResponse = authLogoutPostWithHttpInfo(authLogoutPostRequest = authLogoutPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> Unit
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Logout
+ *
+ * @param authLogoutPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authLogoutPostWithHttpInfo(authLogoutPostRequest: AuthLogoutPostRequest) : ApiResponse {
+ val localVariableConfig = authLogoutPostRequestConfig(authLogoutPostRequest = authLogoutPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authLogoutPost
+ *
+ * @param authLogoutPostRequest
+ * @return RequestConfig
+ */
+ fun authLogoutPostRequestConfig(authLogoutPostRequest: AuthLogoutPostRequest) : RequestConfig {
+ val localVariableBody = authLogoutPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/logout",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Refresh auth tokens
+ *
+ * @param authLogoutPostRequest
+ * @return UserWithTokens
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authRefreshTokensPost(authLogoutPostRequest: AuthLogoutPostRequest) : UserWithTokens {
+ val localVarResponse = authRefreshTokensPostWithHttpInfo(authLogoutPostRequest = authLogoutPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as UserWithTokens
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Refresh auth tokens
+ *
+ * @param authLogoutPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authRefreshTokensPostWithHttpInfo(authLogoutPostRequest: AuthLogoutPostRequest) : ApiResponse {
+ val localVariableConfig = authRefreshTokensPostRequestConfig(authLogoutPostRequest = authLogoutPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authRefreshTokensPost
+ *
+ * @param authLogoutPostRequest
+ * @return RequestConfig
+ */
+ fun authRefreshTokensPostRequestConfig(authLogoutPostRequest: AuthLogoutPostRequest) : RequestConfig {
+ val localVariableBody = authLogoutPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/refresh-tokens",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Register as user
+ *
+ * @param authRegisterPostRequest
+ * @return AuthRegisterPost201Response
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authRegisterPost(authRegisterPostRequest: AuthRegisterPostRequest) : AuthRegisterPost201Response {
+ val localVarResponse = authRegisterPostWithHttpInfo(authRegisterPostRequest = authRegisterPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as AuthRegisterPost201Response
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Register as user
+ *
+ * @param authRegisterPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authRegisterPostWithHttpInfo(authRegisterPostRequest: AuthRegisterPostRequest) : ApiResponse {
+ val localVariableConfig = authRegisterPostRequestConfig(authRegisterPostRequest = authRegisterPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authRegisterPost
+ *
+ * @param authRegisterPostRequest
+ * @return RequestConfig
+ */
+ fun authRegisterPostRequestConfig(authRegisterPostRequest: AuthRegisterPostRequest) : RequestConfig {
+ val localVariableBody = authRegisterPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/register",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Reset password
+ *
+ * @param token The reset password token
+ * @param authResetPasswordPostRequest
+ * @return void
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authResetPasswordPost(token: kotlin.String, authResetPasswordPostRequest: AuthResetPasswordPostRequest) : Unit {
+ val localVarResponse = authResetPasswordPostWithHttpInfo(token = token, authResetPasswordPostRequest = authResetPasswordPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> Unit
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Reset password
+ *
+ * @param token The reset password token
+ * @param authResetPasswordPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authResetPasswordPostWithHttpInfo(token: kotlin.String, authResetPasswordPostRequest: AuthResetPasswordPostRequest) : ApiResponse {
+ val localVariableConfig = authResetPasswordPostRequestConfig(token = token, authResetPasswordPostRequest = authResetPasswordPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authResetPasswordPost
+ *
+ * @param token The reset password token
+ * @param authResetPasswordPostRequest
+ * @return RequestConfig
+ */
+ fun authResetPasswordPostRequestConfig(token: kotlin.String, authResetPasswordPostRequest: AuthResetPasswordPostRequest) : RequestConfig {
+ val localVariableBody = authResetPasswordPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf>()
+ .apply {
+ put("token", listOf(token.toString()))
+ }
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/reset-password",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Send verification email
+ * An email will be sent to verify email.
+ * @return void
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authSendVerificationEmailPost() : Unit {
+ val localVarResponse = authSendVerificationEmailPostWithHttpInfo()
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> Unit
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Send verification email
+ * An email will be sent to verify email.
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authSendVerificationEmailPostWithHttpInfo() : ApiResponse {
+ val localVariableConfig = authSendVerificationEmailPostRequestConfig()
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authSendVerificationEmailPost
+ *
+ * @return RequestConfig
+ */
+ fun authSendVerificationEmailPostRequestConfig() : RequestConfig {
+ val localVariableBody = null
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/send-verification-email",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * verify email
+ *
+ * @param token The verify email token
+ * @return void
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun authVerifyEmailPost(token: kotlin.String) : Unit {
+ val localVarResponse = authVerifyEmailPostWithHttpInfo(token = token)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> Unit
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * verify email
+ *
+ * @param token The verify email token
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Throws(IllegalStateException::class, IOException::class)
+ fun authVerifyEmailPostWithHttpInfo(token: kotlin.String) : ApiResponse {
+ val localVariableConfig = authVerifyEmailPostRequestConfig(token = token)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation authVerifyEmailPost
+ *
+ * @param token The verify email token
+ * @return RequestConfig
+ */
+ fun authVerifyEmailPostRequestConfig(token: kotlin.String) : RequestConfig {
+ val localVariableBody = null
+ val localVariableQuery: MultiValueMap = mutableMapOf>()
+ .apply {
+ put("token", listOf(token.toString()))
+ }
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/auth/verify-email",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
+
+ private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String =
+ HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0]
+}
diff --git a/src/main/kotlin/org/trackedout/client/apis/UsersApi.kt b/src/main/kotlin/org/trackedout/client/apis/UsersApi.kt
new file mode 100644
index 0000000..9fcec8d
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/apis/UsersApi.kt
@@ -0,0 +1,448 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.apis
+
+import java.io.IOException
+import okhttp3.OkHttpClient
+import okhttp3.HttpUrl
+
+import org.trackedout.client.models.Error
+import org.trackedout.client.models.User
+import org.trackedout.client.models.UsersGet200Response
+import org.trackedout.client.models.UsersIdPatchRequest
+import org.trackedout.client.models.UsersPostRequest
+
+import com.squareup.moshi.Json
+
+import org.trackedout.client.infrastructure.ApiClient
+import org.trackedout.client.infrastructure.ApiResponse
+import org.trackedout.client.infrastructure.ClientException
+import org.trackedout.client.infrastructure.ClientError
+import org.trackedout.client.infrastructure.ServerException
+import org.trackedout.client.infrastructure.ServerError
+import org.trackedout.client.infrastructure.MultiValueMap
+import org.trackedout.client.infrastructure.PartConfig
+import org.trackedout.client.infrastructure.RequestConfig
+import org.trackedout.client.infrastructure.RequestMethod
+import org.trackedout.client.infrastructure.ResponseType
+import org.trackedout.client.infrastructure.Success
+import org.trackedout.client.infrastructure.toMultiValue
+
+class UsersApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient = ApiClient.defaultClient) : ApiClient(basePath, client) {
+ companion object {
+ @JvmStatic
+ val defaultBasePath: String by lazy {
+ System.getProperties().getProperty(ApiClient.baseUrlKey, "http://localhost:3000/v1")
+ }
+ }
+
+ /**
+ * Get all users
+ * Only admins can retrieve all users.
+ * @param name User name (optional)
+ * @param role User role (optional)
+ * @param sortBy sort by query in the form of field:desc/asc (ex. name:asc) (optional)
+ * @param projectBy project by query in the form of field:hide/include (ex. name:hide) (optional)
+ * @param limit Maximum number of users (optional)
+ * @param page Page number (optional, default to 1)
+ * @return UsersGet200Response
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun usersGet(name: kotlin.String? = null, role: kotlin.String? = null, sortBy: kotlin.String? = null, projectBy: kotlin.String? = null, limit: kotlin.Int? = null, page: kotlin.Int? = 1) : UsersGet200Response {
+ val localVarResponse = usersGetWithHttpInfo(name = name, role = role, sortBy = sortBy, projectBy = projectBy, limit = limit, page = page)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as UsersGet200Response
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Get all users
+ * Only admins can retrieve all users.
+ * @param name User name (optional)
+ * @param role User role (optional)
+ * @param sortBy sort by query in the form of field:desc/asc (ex. name:asc) (optional)
+ * @param projectBy project by query in the form of field:hide/include (ex. name:hide) (optional)
+ * @param limit Maximum number of users (optional)
+ * @param page Page number (optional, default to 1)
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun usersGetWithHttpInfo(name: kotlin.String?, role: kotlin.String?, sortBy: kotlin.String?, projectBy: kotlin.String?, limit: kotlin.Int?, page: kotlin.Int?) : ApiResponse {
+ val localVariableConfig = usersGetRequestConfig(name = name, role = role, sortBy = sortBy, projectBy = projectBy, limit = limit, page = page)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation usersGet
+ *
+ * @param name User name (optional)
+ * @param role User role (optional)
+ * @param sortBy sort by query in the form of field:desc/asc (ex. name:asc) (optional)
+ * @param projectBy project by query in the form of field:hide/include (ex. name:hide) (optional)
+ * @param limit Maximum number of users (optional)
+ * @param page Page number (optional, default to 1)
+ * @return RequestConfig
+ */
+ fun usersGetRequestConfig(name: kotlin.String?, role: kotlin.String?, sortBy: kotlin.String?, projectBy: kotlin.String?, limit: kotlin.Int?, page: kotlin.Int?) : RequestConfig {
+ val localVariableBody = null
+ val localVariableQuery: MultiValueMap = mutableMapOf>()
+ .apply {
+ if (name != null) {
+ put("name", listOf(name.toString()))
+ }
+ if (role != null) {
+ put("role", listOf(role.toString()))
+ }
+ if (sortBy != null) {
+ put("sortBy", listOf(sortBy.toString()))
+ }
+ if (projectBy != null) {
+ put("projectBy", listOf(projectBy.toString()))
+ }
+ if (limit != null) {
+ put("limit", listOf(limit.toString()))
+ }
+ if (page != null) {
+ put("page", listOf(page.toString()))
+ }
+ }
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.GET,
+ path = "/users",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Delete a user
+ * Logged in users can delete only themselves. Only admins can delete other users.
+ * @param id User id
+ * @return void
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun usersIdDelete(id: kotlin.String) : Unit {
+ val localVarResponse = usersIdDeleteWithHttpInfo(id = id)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> Unit
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Delete a user
+ * Logged in users can delete only themselves. Only admins can delete other users.
+ * @param id User id
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Throws(IllegalStateException::class, IOException::class)
+ fun usersIdDeleteWithHttpInfo(id: kotlin.String) : ApiResponse {
+ val localVariableConfig = usersIdDeleteRequestConfig(id = id)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation usersIdDelete
+ *
+ * @param id User id
+ * @return RequestConfig
+ */
+ fun usersIdDeleteRequestConfig(id: kotlin.String) : RequestConfig {
+ val localVariableBody = null
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.DELETE,
+ path = "/users/{id}".replace("{"+"id"+"}", encodeURIComponent(id.toString())),
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Get a user
+ * Logged in users can fetch only their own user information. Only admins can fetch other users.
+ * @param id User id
+ * @return User
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun usersIdGet(id: kotlin.String) : User {
+ val localVarResponse = usersIdGetWithHttpInfo(id = id)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as User
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Get a user
+ * Logged in users can fetch only their own user information. Only admins can fetch other users.
+ * @param id User id
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun usersIdGetWithHttpInfo(id: kotlin.String) : ApiResponse {
+ val localVariableConfig = usersIdGetRequestConfig(id = id)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation usersIdGet
+ *
+ * @param id User id
+ * @return RequestConfig
+ */
+ fun usersIdGetRequestConfig(id: kotlin.String) : RequestConfig {
+ val localVariableBody = null
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.GET,
+ path = "/users/{id}".replace("{"+"id"+"}", encodeURIComponent(id.toString())),
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Update a user
+ * Logged in users can only update their own information. Only admins can update other users.
+ * @param id User id
+ * @param usersIdPatchRequest
+ * @return User
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun usersIdPatch(id: kotlin.String, usersIdPatchRequest: UsersIdPatchRequest) : User {
+ val localVarResponse = usersIdPatchWithHttpInfo(id = id, usersIdPatchRequest = usersIdPatchRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as User
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Update a user
+ * Logged in users can only update their own information. Only admins can update other users.
+ * @param id User id
+ * @param usersIdPatchRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun usersIdPatchWithHttpInfo(id: kotlin.String, usersIdPatchRequest: UsersIdPatchRequest) : ApiResponse {
+ val localVariableConfig = usersIdPatchRequestConfig(id = id, usersIdPatchRequest = usersIdPatchRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation usersIdPatch
+ *
+ * @param id User id
+ * @param usersIdPatchRequest
+ * @return RequestConfig
+ */
+ fun usersIdPatchRequestConfig(id: kotlin.String, usersIdPatchRequest: UsersIdPatchRequest) : RequestConfig {
+ val localVariableBody = usersIdPatchRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.PATCH,
+ path = "/users/{id}".replace("{"+"id"+"}", encodeURIComponent(id.toString())),
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+ /**
+ * Create a user
+ * Only admins can create other users.
+ * @param usersPostRequest
+ * @return User
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun usersPost(usersPostRequest: UsersPostRequest) : User {
+ val localVarResponse = usersPostWithHttpInfo(usersPostRequest = usersPostRequest)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as User
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Create a user
+ * Only admins can create other users.
+ * @param usersPostRequest
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun usersPostWithHttpInfo(usersPostRequest: UsersPostRequest) : ApiResponse {
+ val localVariableConfig = usersPostRequestConfig(usersPostRequest = usersPostRequest)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation usersPost
+ *
+ * @param usersPostRequest
+ * @return RequestConfig
+ */
+ fun usersPostRequestConfig(usersPostRequest: UsersPostRequest) : RequestConfig {
+ val localVariableBody = usersPostRequest
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/users",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+
+ private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String =
+ HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0]
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/ApiAbstractions.kt b/src/main/kotlin/org/trackedout/client/infrastructure/ApiAbstractions.kt
new file mode 100644
index 0000000..cbcacce
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/ApiAbstractions.kt
@@ -0,0 +1,23 @@
+package org.trackedout.client.infrastructure
+
+typealias MultiValueMap = MutableMap>
+
+fun collectionDelimiter(collectionFormat: String) = when(collectionFormat) {
+ "csv" -> ","
+ "tsv" -> "\t"
+ "pipe" -> "|"
+ "space" -> " "
+ else -> ""
+}
+
+val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" }
+
+fun toMultiValue(items: Array, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter)
+ = toMultiValue(items.asIterable(), collectionFormat, map)
+
+fun toMultiValue(items: Iterable, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List {
+ return when(collectionFormat) {
+ "multi" -> items.map(map)
+ else -> listOf(items.joinToString(separator = collectionDelimiter(collectionFormat), transform = map))
+ }
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/ApiClient.kt b/src/main/kotlin/org/trackedout/client/infrastructure/ApiClient.kt
new file mode 100644
index 0000000..50161c1
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/ApiClient.kt
@@ -0,0 +1,261 @@
+package org.trackedout.client.infrastructure
+
+import okhttp3.OkHttpClient
+import okhttp3.RequestBody
+import okhttp3.RequestBody.Companion.asRequestBody
+import okhttp3.RequestBody.Companion.toRequestBody
+import okhttp3.FormBody
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.ResponseBody
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.Request
+import okhttp3.Headers
+import okhttp3.Headers.Companion.toHeaders
+import okhttp3.MultipartBody
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.Response
+import okhttp3.internal.EMPTY_REQUEST
+import java.io.BufferedWriter
+import java.io.File
+import java.io.FileWriter
+import java.io.IOException
+import java.net.URLConnection
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.LocalTime
+import java.time.OffsetDateTime
+import java.time.OffsetTime
+import java.util.Locale
+import com.squareup.moshi.adapter
+
+open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) {
+ companion object {
+ protected const val ContentType = "Content-Type"
+ protected const val Accept = "Accept"
+ protected const val Authorization = "Authorization"
+ protected const val JsonMediaType = "application/json"
+ protected const val FormDataMediaType = "multipart/form-data"
+ protected const val FormUrlEncMediaType = "application/x-www-form-urlencoded"
+ protected const val XmlMediaType = "application/xml"
+ protected const val OctetMediaType = "application/octet-stream"
+
+ val apiKey: MutableMap = mutableMapOf()
+ val apiKeyPrefix: MutableMap = mutableMapOf()
+ var username: String? = null
+ var password: String? = null
+ var accessToken: String? = null
+ const val baseUrlKey = "org.trackedout.client.baseUrl"
+
+ @JvmStatic
+ val defaultClient: OkHttpClient by lazy {
+ builder.build()
+ }
+
+ @JvmStatic
+ val builder: OkHttpClient.Builder = OkHttpClient.Builder()
+ }
+
+ /**
+ * Guess Content-Type header from the given file (defaults to "application/octet-stream").
+ *
+ * @param file The given file
+ * @return The guessed Content-Type
+ */
+ protected fun guessContentTypeFromFile(file: File): String {
+ val contentType = URLConnection.guessContentTypeFromName(file.name)
+ return contentType ?: "application/octet-stream"
+ }
+
+ protected inline fun requestBody(content: T, mediaType: String?): RequestBody =
+ when {
+ content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
+ mediaType == FormDataMediaType ->
+ MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .apply {
+ // content's type *must* be Map>
+ @Suppress("UNCHECKED_CAST")
+ (content as Map>).forEach { (name, part) ->
+ if (part.body is File) {
+ val partHeaders = part.headers.toMutableMap() +
+ ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
+ val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
+ addPart(
+ partHeaders.toHeaders(),
+ part.body.asRequestBody(fileMediaType)
+ )
+ } else {
+ val partHeaders = part.headers.toMutableMap() +
+ ("Content-Disposition" to "form-data; name=\"$name\"")
+ addPart(
+ partHeaders.toHeaders(),
+ parameterToString(part.body).toRequestBody(null)
+ )
+ }
+ }
+ }.build()
+ mediaType == FormUrlEncMediaType -> {
+ FormBody.Builder().apply {
+ // content's type *must* be Map>
+ @Suppress("UNCHECKED_CAST")
+ (content as Map>).forEach { (name, part) ->
+ add(name, parameterToString(part.body))
+ }
+ }.build()
+ }
+ mediaType == null || mediaType.startsWith("application/") && mediaType.endsWith("json") ->
+ if (content == null) {
+ EMPTY_REQUEST
+ } else {
+ Serializer.moshi.adapter(T::class.java).toJson(content)
+ .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull())
+ }
+ mediaType == XmlMediaType -> throw UnsupportedOperationException("xml not currently supported.")
+ mediaType == OctetMediaType && content is ByteArray ->
+ content.toRequestBody(OctetMediaType.toMediaTypeOrNull())
+ // TODO: this should be extended with other serializers
+ else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.")
+ }
+
+ @OptIn(ExperimentalStdlibApi::class)
+ protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? {
+ if(body == null) {
+ return null
+ }
+ if (T::class.java == File::class.java) {
+ // return tempFile
+ // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options
+ val tempFile = java.nio.file.Files.createTempFile("tmp.org.trackedout.client", null).toFile()
+ tempFile.deleteOnExit()
+ body.byteStream().use { inputStream ->
+ tempFile.outputStream().use { tempFileOutputStream ->
+ inputStream.copyTo(tempFileOutputStream)
+ }
+ }
+ return tempFile as T
+ }
+
+ return when {
+ mediaType == null || (mediaType.startsWith("application/") && mediaType.endsWith("json")) -> {
+ val bodyContent = body.string()
+ if (bodyContent.isEmpty()) {
+ return null
+ }
+ Serializer.moshi.adapter().fromJson(bodyContent)
+ }
+ mediaType == OctetMediaType -> body.bytes() as? T
+ else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.")
+ }
+ }
+
+ protected fun updateAuthParams(requestConfig: RequestConfig) {
+ if (requestConfig.headers[Authorization].isNullOrEmpty()) {
+ accessToken?.let { accessToken ->
+ requestConfig.headers[Authorization] = "Bearer $accessToken"
+ }
+ }
+ }
+
+ protected inline fun request(requestConfig: RequestConfig): ApiResponse {
+ val httpUrl = baseUrl.toHttpUrlOrNull() ?: throw IllegalStateException("baseUrl is invalid.")
+
+ // take authMethod from operation
+ updateAuthParams(requestConfig)
+
+ val url = httpUrl.newBuilder()
+ .addEncodedPathSegments(requestConfig.path.trimStart('/'))
+ .apply {
+ requestConfig.query.forEach { query ->
+ query.value.forEach { queryValue ->
+ addQueryParameter(query.key, queryValue)
+ }
+ }
+ }.build()
+
+ // take content-type/accept from spec or set to default (application/json) if not defined
+ if (requestConfig.body != null && requestConfig.headers[ContentType].isNullOrEmpty()) {
+ requestConfig.headers[ContentType] = JsonMediaType
+ }
+ if (requestConfig.headers[Accept].isNullOrEmpty()) {
+ requestConfig.headers[Accept] = JsonMediaType
+ }
+ val headers = requestConfig.headers
+
+ if (headers[Accept].isNullOrEmpty()) {
+ throw kotlin.IllegalStateException("Missing Accept header. This is required.")
+ }
+
+ val contentType = if (headers[ContentType] != null) {
+ // TODO: support multiple contentType options here.
+ (headers[ContentType] as String).substringBefore(";").lowercase(Locale.US)
+ } else {
+ null
+ }
+
+ val request = when (requestConfig.method) {
+ RequestMethod.DELETE -> Request.Builder().url(url).delete(requestBody(requestConfig.body, contentType))
+ RequestMethod.GET -> Request.Builder().url(url)
+ RequestMethod.HEAD -> Request.Builder().url(url).head()
+ RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(requestConfig.body, contentType))
+ RequestMethod.PUT -> Request.Builder().url(url).put(requestBody(requestConfig.body, contentType))
+ RequestMethod.POST -> Request.Builder().url(url).post(requestBody(requestConfig.body, contentType))
+ RequestMethod.OPTIONS -> Request.Builder().url(url).method("OPTIONS", null)
+ }.apply {
+ headers.forEach { header -> addHeader(header.key, header.value) }
+ }.build()
+
+ val response = client.newCall(request).execute()
+
+ val accept = response.header(ContentType)?.substringBefore(";")?.lowercase(Locale.US)
+
+ // TODO: handle specific mapping types. e.g. Map>
+ return when {
+ response.isRedirect -> Redirection(
+ response.code,
+ response.headers.toMultimap()
+ )
+ response.isInformational -> Informational(
+ response.message,
+ response.code,
+ response.headers.toMultimap()
+ )
+ response.isSuccessful -> Success(
+ responseBody(response.body, accept),
+ response.code,
+ response.headers.toMultimap()
+ )
+ response.isClientError -> ClientError(
+ response.message,
+ response.body?.string(),
+ response.code,
+ response.headers.toMultimap()
+ )
+ else -> ServerError(
+ response.message,
+ response.body?.string(),
+ response.code,
+ response.headers.toMultimap()
+ )
+ }
+ }
+
+ protected fun parameterToString(value: Any?): String = when (value) {
+ null -> ""
+ is Array<*> -> toMultiValue(value, "csv").toString()
+ is Iterable<*> -> toMultiValue(value, "csv").toString()
+ is OffsetDateTime, is OffsetTime, is LocalDateTime, is LocalDate, is LocalTime ->
+ parseDateToQueryString(value)
+ else -> value.toString()
+ }
+
+ protected inline fun parseDateToQueryString(value : T): String {
+ /*
+ .replace("\"", "") converts the json object string to an actual string for the query parameter.
+ The moshi or gson adapter allows a more generic solution instead of trying to use a native
+ formatter. It also easily allows to provide a simple way to define a custom date format pattern
+ inside a gson/moshi adapter.
+ */
+ return Serializer.moshi.adapter(T::class.java).toJson(value).replace("\"", "")
+ }
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/ApiResponse.kt b/src/main/kotlin/org/trackedout/client/infrastructure/ApiResponse.kt
new file mode 100644
index 0000000..99cb290
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/ApiResponse.kt
@@ -0,0 +1,43 @@
+package org.trackedout.client.infrastructure
+
+enum class ResponseType {
+ Success, Informational, Redirection, ClientError, ServerError
+}
+
+interface Response
+
+abstract class ApiResponse(val responseType: ResponseType): Response {
+ abstract val statusCode: Int
+ abstract val headers: Map>
+}
+
+class Success(
+ val data: T,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+): ApiResponse(ResponseType.Success)
+
+class Informational(
+ val statusText: String,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+) : ApiResponse(ResponseType.Informational)
+
+class Redirection(
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+) : ApiResponse(ResponseType.Redirection)
+
+class ClientError(
+ val message: String? = null,
+ val body: Any? = null,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+) : ApiResponse(ResponseType.ClientError)
+
+class ServerError(
+ val message: String? = null,
+ val body: Any? = null,
+ override val statusCode: Int = -1,
+ override val headers: Map>
+): ApiResponse(ResponseType.ServerError)
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/BigDecimalAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/BigDecimalAdapter.kt
new file mode 100644
index 0000000..a923d70
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/BigDecimalAdapter.kt
@@ -0,0 +1,17 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.math.BigDecimal
+
+class BigDecimalAdapter {
+ @ToJson
+ fun toJson(value: BigDecimal): String {
+ return value.toPlainString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigDecimal {
+ return BigDecimal(value)
+ }
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/BigIntegerAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/BigIntegerAdapter.kt
new file mode 100644
index 0000000..b60db10
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/BigIntegerAdapter.kt
@@ -0,0 +1,17 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.math.BigInteger
+
+class BigIntegerAdapter {
+ @ToJson
+ fun toJson(value: BigInteger): String {
+ return value.toString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigInteger {
+ return BigInteger(value)
+ }
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/ByteArrayAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/ByteArrayAdapter.kt
new file mode 100644
index 0000000..269cc49
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/ByteArrayAdapter.kt
@@ -0,0 +1,12 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+
+class ByteArrayAdapter {
+ @ToJson
+ fun toJson(data: ByteArray): String = String(data)
+
+ @FromJson
+ fun fromJson(data: String): ByteArray = data.toByteArray()
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/Errors.kt b/src/main/kotlin/org/trackedout/client/infrastructure/Errors.kt
new file mode 100644
index 0000000..93ca575
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/Errors.kt
@@ -0,0 +1,18 @@
+@file:Suppress("unused")
+package org.trackedout.client.infrastructure
+
+import java.lang.RuntimeException
+
+open class ClientException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) {
+
+ companion object {
+ private const val serialVersionUID: Long = 123L
+ }
+}
+
+open class ServerException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) {
+
+ companion object {
+ private const val serialVersionUID: Long = 456L
+ }
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/LocalDateAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/LocalDateAdapter.kt
new file mode 100644
index 0000000..92ee9dc
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/LocalDateAdapter.kt
@@ -0,0 +1,19 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+
+class LocalDateAdapter {
+ @ToJson
+ fun toJson(value: LocalDate): String {
+ return DateTimeFormatter.ISO_LOCAL_DATE.format(value)
+ }
+
+ @FromJson
+ fun fromJson(value: String): LocalDate {
+ return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE)
+ }
+
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/LocalDateTimeAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/LocalDateTimeAdapter.kt
new file mode 100644
index 0000000..08d7466
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/LocalDateTimeAdapter.kt
@@ -0,0 +1,19 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
+
+class LocalDateTimeAdapter {
+ @ToJson
+ fun toJson(value: LocalDateTime): String {
+ return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value)
+ }
+
+ @FromJson
+ fun fromJson(value: String): LocalDateTime {
+ return LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
+ }
+
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/OffsetDateTimeAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/OffsetDateTimeAdapter.kt
new file mode 100644
index 0000000..b7832cc
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/OffsetDateTimeAdapter.kt
@@ -0,0 +1,19 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.time.OffsetDateTime
+import java.time.format.DateTimeFormatter
+
+class OffsetDateTimeAdapter {
+ @ToJson
+ fun toJson(value: OffsetDateTime): String {
+ return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)
+ }
+
+ @FromJson
+ fun fromJson(value: String): OffsetDateTime {
+ return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
+ }
+
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/PartConfig.kt b/src/main/kotlin/org/trackedout/client/infrastructure/PartConfig.kt
new file mode 100644
index 0000000..78ad2cb
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/PartConfig.kt
@@ -0,0 +1,11 @@
+package org.trackedout.client.infrastructure
+
+/**
+ * Defines a config object for a given part of a multi-part request.
+ * NOTE: Headers is a Map because rfc2616 defines
+ * multi-valued headers as csv-only.
+ */
+data class PartConfig(
+ val headers: MutableMap = mutableMapOf(),
+ val body: T? = null
+)
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/RequestConfig.kt b/src/main/kotlin/org/trackedout/client/infrastructure/RequestConfig.kt
new file mode 100644
index 0000000..86f047b
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/RequestConfig.kt
@@ -0,0 +1,18 @@
+package org.trackedout.client.infrastructure
+
+/**
+ * Defines a config object for a given request.
+ * NOTE: This object doesn't include 'body' because it
+ * allows for caching of the constructed object
+ * for many request definitions.
+ * NOTE: Headers is a Map because rfc2616 defines
+ * multi-valued headers as csv-only.
+ */
+data class RequestConfig(
+ val method: RequestMethod,
+ val path: String,
+ val headers: MutableMap = mutableMapOf(),
+ val query: MutableMap> = mutableMapOf(),
+ val requiresAuthentication: Boolean,
+ val body: T? = null
+)
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/RequestMethod.kt b/src/main/kotlin/org/trackedout/client/infrastructure/RequestMethod.kt
new file mode 100644
index 0000000..73438a3
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/RequestMethod.kt
@@ -0,0 +1,8 @@
+package org.trackedout.client.infrastructure
+
+/**
+ * Provides enumerated HTTP verbs
+ */
+enum class RequestMethod {
+ GET, DELETE, HEAD, OPTIONS, PATCH, POST, PUT
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/ResponseExtensions.kt b/src/main/kotlin/org/trackedout/client/infrastructure/ResponseExtensions.kt
new file mode 100644
index 0000000..5a0297a
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/ResponseExtensions.kt
@@ -0,0 +1,24 @@
+package org.trackedout.client.infrastructure
+
+import okhttp3.Response
+
+/**
+ * Provides an extension to evaluation whether the response is a 1xx code
+ */
+val Response.isInformational : Boolean get() = this.code in 100..199
+
+/**
+ * Provides an extension to evaluation whether the response is a 3xx code
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+val Response.isRedirect : Boolean get() = this.code in 300..399
+
+/**
+ * Provides an extension to evaluation whether the response is a 4xx code
+ */
+val Response.isClientError : Boolean get() = this.code in 400..499
+
+/**
+ * Provides an extension to evaluation whether the response is a 5xx (Standard) through 999 (non-standard) code
+ */
+val Response.isServerError : Boolean get() = this.code in 500..999
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/Serializer.kt b/src/main/kotlin/org/trackedout/client/infrastructure/Serializer.kt
new file mode 100644
index 0000000..e5a311f
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/Serializer.kt
@@ -0,0 +1,23 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
+
+object Serializer {
+ @JvmStatic
+ val moshiBuilder: Moshi.Builder = Moshi.Builder()
+ .add(OffsetDateTimeAdapter())
+ .add(LocalDateTimeAdapter())
+ .add(LocalDateAdapter())
+ .add(UUIDAdapter())
+ .add(ByteArrayAdapter())
+ .add(URIAdapter())
+ .add(KotlinJsonAdapterFactory())
+ .add(BigDecimalAdapter())
+ .add(BigIntegerAdapter())
+
+ @JvmStatic
+ val moshi: Moshi by lazy {
+ moshiBuilder.build()
+ }
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/URIAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/URIAdapter.kt
new file mode 100644
index 0000000..78080b5
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/URIAdapter.kt
@@ -0,0 +1,13 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.net.URI
+
+class URIAdapter {
+ @ToJson
+ fun toJson(uri: URI) = uri.toString()
+
+ @FromJson
+ fun fromJson(s: String): URI = URI.create(s)
+}
diff --git a/src/main/kotlin/org/trackedout/client/infrastructure/UUIDAdapter.kt b/src/main/kotlin/org/trackedout/client/infrastructure/UUIDAdapter.kt
new file mode 100644
index 0000000..92fba35
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/infrastructure/UUIDAdapter.kt
@@ -0,0 +1,13 @@
+package org.trackedout.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.util.UUID
+
+class UUIDAdapter {
+ @ToJson
+ fun toJson(uuid: UUID) = uuid.toString()
+
+ @FromJson
+ fun fromJson(s: String): UUID = UUID.fromString(s)
+}
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthForgotPasswordPostRequest.kt b/src/main/kotlin/org/trackedout/client/models/AuthForgotPasswordPostRequest.kt
new file mode 100644
index 0000000..6ad4a36
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthForgotPasswordPostRequest.kt
@@ -0,0 +1,35 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param email
+ */
+
+
+data class AuthForgotPasswordPostRequest (
+
+ @Json(name = "email")
+ val email: kotlin.String
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthLoginPostRequest.kt b/src/main/kotlin/org/trackedout/client/models/AuthLoginPostRequest.kt
new file mode 100644
index 0000000..ece5184
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthLoginPostRequest.kt
@@ -0,0 +1,39 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param email
+ * @param password
+ */
+
+
+data class AuthLoginPostRequest (
+
+ @Json(name = "email")
+ val email: kotlin.String,
+
+ @Json(name = "password")
+ val password: kotlin.String
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthLogoutPostRequest.kt b/src/main/kotlin/org/trackedout/client/models/AuthLogoutPostRequest.kt
new file mode 100644
index 0000000..8b14c4d
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthLogoutPostRequest.kt
@@ -0,0 +1,35 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param refreshToken
+ */
+
+
+data class AuthLogoutPostRequest (
+
+ @Json(name = "refreshToken")
+ val refreshToken: kotlin.String
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthRegisterPost201Response.kt b/src/main/kotlin/org/trackedout/client/models/AuthRegisterPost201Response.kt
new file mode 100644
index 0000000..d5baef9
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthRegisterPost201Response.kt
@@ -0,0 +1,41 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+import org.trackedout.client.models.AuthTokens
+import org.trackedout.client.models.User
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param user
+ * @param tokens
+ */
+
+
+data class AuthRegisterPost201Response (
+
+ @Json(name = "user")
+ val user: User? = null,
+
+ @Json(name = "tokens")
+ val tokens: AuthTokens? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthRegisterPostRequest.kt b/src/main/kotlin/org/trackedout/client/models/AuthRegisterPostRequest.kt
new file mode 100644
index 0000000..f286b80
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthRegisterPostRequest.kt
@@ -0,0 +1,45 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param name
+ * @param email must be unique
+ * @param password At least one number and one letter
+ */
+
+
+data class AuthRegisterPostRequest (
+
+ @Json(name = "name")
+ val name: kotlin.String,
+
+ /* must be unique */
+ @Json(name = "email")
+ val email: kotlin.String,
+
+ /* At least one number and one letter */
+ @Json(name = "password")
+ val password: kotlin.String
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthResetPasswordPostRequest.kt b/src/main/kotlin/org/trackedout/client/models/AuthResetPasswordPostRequest.kt
new file mode 100644
index 0000000..bbf4334
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthResetPasswordPostRequest.kt
@@ -0,0 +1,36 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param password At least one number and one letter
+ */
+
+
+data class AuthResetPasswordPostRequest (
+
+ /* At least one number and one letter */
+ @Json(name = "password")
+ val password: kotlin.String
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/AuthTokens.kt b/src/main/kotlin/org/trackedout/client/models/AuthTokens.kt
new file mode 100644
index 0000000..c21e1ed
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/AuthTokens.kt
@@ -0,0 +1,40 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+import org.trackedout.client.models.Token
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param access
+ * @param refresh
+ */
+
+
+data class AuthTokens (
+
+ @Json(name = "access")
+ val access: Token? = null,
+
+ @Json(name = "refresh")
+ val refresh: Token? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/Error.kt b/src/main/kotlin/org/trackedout/client/models/Error.kt
new file mode 100644
index 0000000..a6ff9bf
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/Error.kt
@@ -0,0 +1,39 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param code
+ * @param message
+ */
+
+
+data class Error (
+
+ @Json(name = "code")
+ val code: java.math.BigDecimal? = null,
+
+ @Json(name = "message")
+ val message: kotlin.String? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/Token.kt b/src/main/kotlin/org/trackedout/client/models/Token.kt
new file mode 100644
index 0000000..cf65be3
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/Token.kt
@@ -0,0 +1,39 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param token
+ * @param expires
+ */
+
+
+data class Token (
+
+ @Json(name = "token")
+ val token: kotlin.String? = null,
+
+ @Json(name = "expires")
+ val expires: java.time.OffsetDateTime? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/User.kt b/src/main/kotlin/org/trackedout/client/models/User.kt
new file mode 100644
index 0000000..2a46de0
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/User.kt
@@ -0,0 +1,59 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param id
+ * @param email
+ * @param name
+ * @param role
+ */
+
+
+data class User (
+
+ @Json(name = "id")
+ val id: kotlin.String? = null,
+
+ @Json(name = "email")
+ val email: kotlin.String? = null,
+
+ @Json(name = "name")
+ val name: kotlin.String? = null,
+
+ @Json(name = "role")
+ val role: User.Role? = null
+
+) {
+
+ /**
+ *
+ *
+ * Values: user,admin
+ */
+ @JsonClass(generateAdapter = false)
+ enum class Role(val value: kotlin.String) {
+ @Json(name = "user") user("user"),
+ @Json(name = "admin") admin("admin");
+ }
+}
+
diff --git a/src/main/kotlin/org/trackedout/client/models/UserWithTokens.kt b/src/main/kotlin/org/trackedout/client/models/UserWithTokens.kt
new file mode 100644
index 0000000..579554c
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/UserWithTokens.kt
@@ -0,0 +1,41 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+import org.trackedout.client.models.AuthTokens
+import org.trackedout.client.models.User
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param user
+ * @param tokens
+ */
+
+
+data class UserWithTokens (
+
+ @Json(name = "user")
+ val user: User? = null,
+
+ @Json(name = "tokens")
+ val tokens: AuthTokens? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/UsersGet200Response.kt b/src/main/kotlin/org/trackedout/client/models/UsersGet200Response.kt
new file mode 100644
index 0000000..97de484
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/UsersGet200Response.kt
@@ -0,0 +1,52 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+import org.trackedout.client.models.User
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param results
+ * @param page
+ * @param limit
+ * @param totalPages
+ * @param totalResults
+ */
+
+
+data class UsersGet200Response (
+
+ @Json(name = "results")
+ val results: kotlin.collections.List? = null,
+
+ @Json(name = "page")
+ val page: kotlin.Int? = null,
+
+ @Json(name = "limit")
+ val limit: kotlin.Int? = null,
+
+ @Json(name = "totalPages")
+ val totalPages: kotlin.Int? = null,
+
+ @Json(name = "totalResults")
+ val totalResults: kotlin.Int? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/UsersIdPatchRequest.kt b/src/main/kotlin/org/trackedout/client/models/UsersIdPatchRequest.kt
new file mode 100644
index 0000000..c7de747
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/UsersIdPatchRequest.kt
@@ -0,0 +1,45 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param name
+ * @param email must be unique
+ * @param password At least one number and one letter
+ */
+
+
+data class UsersIdPatchRequest (
+
+ @Json(name = "name")
+ val name: kotlin.String? = null,
+
+ /* must be unique */
+ @Json(name = "email")
+ val email: kotlin.String? = null,
+
+ /* At least one number and one letter */
+ @Json(name = "password")
+ val password: kotlin.String? = null
+
+)
+
diff --git a/src/main/kotlin/org/trackedout/client/models/UsersPostRequest.kt b/src/main/kotlin/org/trackedout/client/models/UsersPostRequest.kt
new file mode 100644
index 0000000..bed5f5b
--- /dev/null
+++ b/src/main/kotlin/org/trackedout/client/models/UsersPostRequest.kt
@@ -0,0 +1,61 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.trackedout.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param name
+ * @param email must be unique
+ * @param password At least one number and one letter
+ * @param role
+ */
+
+
+data class UsersPostRequest (
+
+ @Json(name = "name")
+ val name: kotlin.String,
+
+ /* must be unique */
+ @Json(name = "email")
+ val email: kotlin.String,
+
+ /* At least one number and one letter */
+ @Json(name = "password")
+ val password: kotlin.String,
+
+ @Json(name = "role")
+ val role: UsersPostRequest.Role
+
+) {
+
+ /**
+ *
+ *
+ * Values: user,admin
+ */
+ @JsonClass(generateAdapter = false)
+ enum class Role(val value: kotlin.String) {
+ @Json(name = "user") user("user"),
+ @Json(name = "admin") admin("admin");
+ }
+}
+