Skip to content

Commit

Permalink
Merge branch 'master' of github.com:TinkoffCreditSystems/typed-schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Odomontois committed Oct 16, 2020
2 parents fc08647 + 1d079b1 commit 3020933
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ binPack.parentConstructors = true
maxColumn = 120
includeCurlyBraceInSelectChains = false
align.preset = most
version = "2.7.3"
version = "2.7.4"
trailingCommas = preserve
newlines.penalizeSingleSelectMultiArgList = false
newlines.alwaysBeforeMultilineDef = false
2 changes: 1 addition & 1 deletion examples/project/Version.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ object Version {

val typedSchema = "0.12.6"

val swaggerUI = "3.35.1"
val swaggerUI = "3.35.2"
}
90 changes: 30 additions & 60 deletions modules/kernel/src/main/scala/ru/tinkoff/tschema/typeDSL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,20 @@ object typeDSL {
trait CanHoldApiKey
trait DSLAtomAuth extends DSLAtom

/**
* Any path component that is subtype of Meta will be ignored
/** Any path component that is subtype of Meta will be ignored
* by `Serve` but could support additional information like swagger tags or descriptions
*/
trait Meta extends DSLAtom

/**
* tagging symbol for route
/** tagging symbol for route
*/
class Tag[tag] extends Meta

/**
* mark operation as deprecated
/** mark operation as deprecated
*/
class Deprecated extends Meta

/**
* naming symbol of single route in complex route
/** naming symbol of single route in complex route
*/
class Key[key] extends DSLAtom

Expand All @@ -34,8 +30,7 @@ object typeDSL {
def of[key]: Key[key] = anyKey.asInstanceOf[Key[key]]
}

/**
* naming intermediate group of methods
/** naming intermediate group of methods
*/
class Group[key] extends DSLAtom

Expand All @@ -44,170 +39,145 @@ object typeDSL {
def of[key]: Group[key] = anyGroup.asInstanceOf[Group[key]]
}

/**
* return query params as Map[String, String]
/** return query params as Map[String, String]
*/
final class AllQuery[name] extends DSLAtom

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* does not check HTTP method
*/
final class Complete[x] extends DSLDef

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via POST HTTP method
*/
final class Post extends DSLMethod

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via GET HTTP method
*/
final class Get extends DSLMethod

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via PUT HTTP method
*/
final class Put extends DSLMethod

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via DELETE HTTP method
*/
final class Delete extends DSLMethod

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via HEAD HTTP method
*/
final class Head extends DSLMethod

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via OPTIONS HTTP method
*/
final class Options extends DSLMethod

/**
* indicates result of element of type `x`
/** indicates result of element of type `x`
* via PATCH HTTP method
*/
final class Patch extends DSLMethod

/**
* Indicated single path prefix
/** Indicated single path prefix
* Could be replaced by it's parameter
*
* @tparam pref singleton string
*/
final class Prefix[pref] extends DSLAtom

/**
* captures param from query
/** captures param from query
*
* @tparam name name of param
* @tparam x type of param, should have instance of `FromQueryParam`
*/
final class QueryParamAs[name, p, x] extends DSLAtom with CanHoldApiKey
type QueryParam[name, x] = QueryParamAs[name, name, x]

/**
* captures param from path element
/** captures param from path element
*
* @tparam name name of param, have no effect to routing
* @tparam x type of param, should have instance of `FromPathParam`
*/
final class CaptureAs[name, p, x] extends DSLAtom
type Capture[name, x] = CaptureAs[name, name, x]

/**
* captures param list from query
/** captures param list from query
*
* @tparam name name of param
* @tparam x type of param, should have instance of `FromQueryParam`
*/
final class QueryParamsAs[name, p, x] extends DSLAtom
type QueryParams[name, x] = QueryParamsAs[name, name, x]

/**
* captures fact of provision of param in query
/** captures fact of provision of param in query
*
* @tparam name name of param
*/
final class QueryFlagAs[name, p] extends DSLAtom
type QueryFlag[name] = QueryFlagAs[name, name]

/**
* captures request body and unmarshalls in to requested type
/** captures request body and unmarshalls in to requested type
*
* @tparam x type of body, should have `FromRequestUnmarshaller` instance
*/
final class ReqBodyAs[name, p, x] extends DSLAtom
type ReqBody[name, x] = ReqBodyAs[name, name, x]

/**
* captures header value
/** captures header value
*
* @tparam name header name
* @tparam x parameter type, should have `FromHeader` instance
*/
final class HeaderAs[name, p, x] extends DSLAtom with CanHoldApiKey
type Header[name, x] = HeaderAs[name, name, x]

/**
* captures field value from form data
/** captures field value from form data
*
* @tparam name field name
* @tparam x parameter type, should have `FromFormParam` instance
*/
final class FormFieldAs[name, p, x] extends DSLAtom
type FormField[name, x] = FormFieldAs[name, name, x]

/**
* captures field value from Cookie
/** captures field value from Cookie
*/
final class CookieAs[name, p, x] extends DSLAtom with CanHoldApiKey
type Cookie[name, x] = CookieAs[name, name, x]

/**
* defines basic authentication scheme
/** defines basic authentication scheme
*/
final class BasicAuth[realm, name, T] extends DSLAtomAuth

/**
* defines bearer authentication scheme
/** defines bearer authentication scheme
*/
final class BearerAuth[realm, name, T] extends DSLAtomAuth

/**
* defines oauth2 authentication
/** defines oauth2 authentication
*/
final class OAuth2Auth[+T, R, conf, name] extends DSLAtomAuth

/**
* defines api key authentication scheme
/** defines api key authentication scheme
* @tparam Param on of: Header, Cookie or Query
*/
final class ApiKeyAuth[realm, Param <: CanHoldApiKey] extends DSLAtomAuth

/**
* transforms directive to rename provided parameter with given name
/** transforms directive to rename provided parameter with given name
*/
final class As[name] extends DSLAtom

/**
* concatenates pair of paths into complete path
/** concatenates pair of paths into complete path
*
* @tparam path prefix - always simple path without disjunctions
* @tparam postfix postfix
*/
final class :>[path, postfix] extends DSLDef

/**
* disjunction operator
/** disjunction operator
* can be used both for defining API type and for joining different handlers
* resulting type is effectively `Either[left input, right input] => Either[left output, right output]`
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import magnolia.{CaseClass, Magnolia, SealedTrait, TypeName}
import ru.tinkoff.tschema.swagger._
import ru.tinkoff.tschema.swagger.SwaggerTypeable.{Config, seq}

object Swagger extends Derivation[SwaggerTypeable] {
object Swagger extends Derivation[SwaggerTypeable] with SwaggerFunctions {
type Typeclass[T] = SwaggerTypeable[T]

def apply[A](implicit swagger: Swagger[A]): Swagger[A] = swagger
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ru.tinkoff.tschema.swagger

import cats.Eval

trait SwaggerFunctions {
import SwaggerTypeable.make

def typeOf[A](implicit swagger: Swagger[A]): SwaggerType = swagger.typ

def obj[A](props: (String, SwaggerType)*): Swagger[A] = make(
SwaggerObject(
props.map { case (name, typ) => SwaggerProperty(name, None, typ = Eval.now(typ)) }.toVector
)
)

def objLazy[A](props: (String, () => SwaggerType)*): Swagger[A] = make(
SwaggerObject(
props.map { case (name, typ) => SwaggerProperty(name, None, typ = Eval.later(typ())) }.toVector
)
)

def arr[A](t: => SwaggerType): Swagger[A] =
SwaggerTypeable.make(SwaggerArray(Eval.later(t)))

def oneOf[A](ts: SwaggerType*): Swagger[A] = make(
SwaggerOneOf(ts.map(t => None -> Eval.now(t)).toVector)
)

def oneOfLazy[A](ts: () => SwaggerType*): Swagger[A] = make(
SwaggerOneOf(ts.map(t => None -> Eval.later(t())).toVector)
)

def discriminated[A](discriminator: String)(ts: (String, SwaggerType)*): Swagger[A] = make(
SwaggerOneOf(ts.map { case (name, t) => Some(name) -> Eval.now(t) }.toVector)
)

def discriminatedLazy[A](discriminator: String)(ts: (String, () => SwaggerType)*): Swagger[A] =
SwaggerTypeable.make(
SwaggerOneOf(ts.map { case (name, t) => Some(name) -> Eval.later(t()) }.toVector)
)

//usage : Swagger.string(_(format = OpenApiFormat.password, maxLength = 30))
def string[A](create: SwaggerStringValue.type => SwaggerStringValue): Swagger[A] =
SwaggerTypeable.make(
new SwaggerPrimitive(create(SwaggerStringValue))
)

//usage : Swagger.int(_(format = OpenApiFormat.int64, minimum = 1))
def int[A](create: SwaggerIntValue.type => SwaggerIntValue): Swagger[A] =
SwaggerTypeable.make(
new SwaggerPrimitive(create(SwaggerIntValue))
)

def number[A](create: SwaggerNumberValue.type => SwaggerNumberValue): Swagger[A] =
SwaggerTypeable.make(
new SwaggerPrimitive(create(SwaggerNumberValue))
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ sealed trait SwaggerType {

def nameOpt: Option[String] = None

/**
* set ot change type description if this is named type
/** set ot change type description if this is named type
*/
def describe(descr: String) = this

Expand Down Expand Up @@ -126,14 +125,12 @@ final case class SwaggerObject(
})
}

/**
* set or change fields description if this is ObjectType
/** set or change fields description if this is ObjectType
*/
def describeFields(descrs: (String, String)*) =
updateProps(descrs)(descr => SwaggerProperty.description.set(_, descr.some))

/**
* set or change XML options if fields
/** set or change XML options if fields
*
* @param opts
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import ru.tinkoff.tschema.utils.transform

import scala.collection.{immutable, mutable}
import scala.reflect.runtime.universe.TypeTag
import tofu.compat.{LazySeq, NELazySeq}

trait SwaggerTypeable[T] {
self =>
Expand All @@ -32,6 +33,9 @@ trait SwaggerTypeable[T] {
def updateTyp(f: SwaggerType => SwaggerType): SwaggerTypeable[T] =
SwaggerTypeable.make[T](f(self.typ))

def updateObject(f: SwaggerObject => SwaggerObject): SwaggerTypeable[T] =
updateTyp(SwaggerType.objProp.update(_, f))

def anon: SwaggerTypeable[T] = new SwaggerTypeable[T] {
override def typ: SwaggerType = self.typ.deref.value
}
Expand Down Expand Up @@ -127,19 +131,19 @@ trait SwaggerTypeableInstances

final implicit val swaggerTypeableJsonObject: SwaggerTypeable[JsonObject] = make[JsonObject](SwaggerObject())

final implicit def swaggerVectorTypeable[T: SwaggerTypeable]: SwaggerTypeable[Vector[T]] = seq[Vector, T]
final implicit def swaggerListTypeable[T: SwaggerTypeable]: SwaggerTypeable[List[T]] = seq[List, T]
final implicit def swaggerSetTypeable[T: SwaggerTypeable]: SwaggerTypeable[Set[T]] = seq[Set, T]
final implicit def swaggerStreamTypeable[T: SwaggerTypeable]: SwaggerTypeable[Stream[T]] = seq[Stream, T]
final implicit def swaggerChainTypeable[T: SwaggerTypeable]: SwaggerTypeable[Chain[T]] = seq[Chain, T]
final implicit def swaggerVectorTypeable[T: SwaggerTypeable]: SwaggerTypeable[Vector[T]] = seq[Vector, T]
final implicit def swaggerListTypeable[T: SwaggerTypeable]: SwaggerTypeable[List[T]] = seq[List, T]
final implicit def swaggerSetTypeable[T: SwaggerTypeable]: SwaggerTypeable[Set[T]] = seq[Set, T]
final implicit def swaggerStreamTypeable[T: SwaggerTypeable]: SwaggerTypeable[LazySeq[T]] = seq[LazySeq, T]
final implicit def swaggerChainTypeable[T: SwaggerTypeable]: SwaggerTypeable[Chain[T]] = seq[Chain, T]

final implicit def swaggerNEVectorTypeable[T: SwaggerTypeable]: SwaggerTypeable[NonEmptyVector[T]] =
neseq[NonEmptyVector, T]
final implicit def swaggerNEListTypeable[T: SwaggerTypeable]: SwaggerTypeable[NonEmptyList[T]] =
neseq[NonEmptyList, T]
final implicit def swaggerNESetTypeable[T: SwaggerTypeable]: SwaggerTypeable[NonEmptySet[T]] = neseq[NonEmptySet, T]
final implicit def swaggerNEStreamTypeable[T: SwaggerTypeable]: SwaggerTypeable[NonEmptyStream[T]] =
neseq[NonEmptyStream, T]
final implicit def swaggerNEStreamTypeable[T: SwaggerTypeable]: SwaggerTypeable[NELazySeq[T]] =
neseq[NELazySeq, T]
final implicit def swaggerNEChainTypeable[T: SwaggerTypeable]: SwaggerTypeable[NonEmptyChain[T]] =
neseq[NonEmptyChain, T]

Expand Down
Loading

0 comments on commit 3020933

Please sign in to comment.