eu.timepit.refined.types.string.NonEmptyString Scala Examples

The following examples show how to use eu.timepit.refined.types.string.NonEmptyString. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: package.scala    From franklin   with Apache License 2.0 6 votes vote down vote up
package com.azavea.franklin.api

import com.azavea.franklin.api.commands.ApiConfig
import com.azavea.stac4s._
import eu.timepit.refined.types.string.NonEmptyString

import java.net.URLEncoder
import java.nio.charset.StandardCharsets

package object implicits {

  implicit class combineNonEmptyString(s: NonEmptyString) {

    // Combining a non-empty string should always return a non-empty string
    def +(otherString: String): NonEmptyString =
      NonEmptyString.unsafeFrom(s.value.concat(otherString))
  }

  implicit class StacItemWithCog(item: StacItem) {

    def updateLinksWithHost(apiConfig: ApiConfig) = {
      val updatedLinks = item.links.map(_.addServerHost(apiConfig))
      val updatedAssets = item.assets.mapValues { asset =>
        asset.href.startsWith("/") match {
          case true => asset.copy(href = s"${apiConfig.apiHost}${asset.href}")
          case _    => asset
        }
      }
      item.copy(links = updatedLinks, assets = updatedAssets)
    }

    def addTilesLink(apiHost: String, collectionId: String, itemId: String) = {
      val cogAsset = item.assets.values.exists { asset =>
        asset._type match {
          case Some(`image/cog`) => true
          case _                 => false
        }
      }
      val updatedLinks = cogAsset match {
        case true => {
          val encodedItemId       = URLEncoder.encode(itemId, StandardCharsets.UTF_8.toString)
          val encodedCollectionId = URLEncoder.encode(collectionId, StandardCharsets.UTF_8.toString)
          val tileLink: StacLink = StacLink(
            s"$apiHost/collections/$encodedCollectionId/items/$encodedItemId/tiles",
            StacLinkType.VendorLinkType("tiles"),
            Some(`application/json`),
            Some("Tile URLs for Item")
          )
          tileLink :: item.links
        }
        case _ => item.links
      }
      (item.copy(links = updatedLinks))
    }

  }

  implicit class UpdatedStacLink(link: StacLink) {

    def addServerHost(apiConfig: ApiConfig) = {
      link.href.startsWith("/") match {
        case true => link.copy(href = s"${apiConfig.apiHost}${link.href}")
        case _    => link
      }
    }
  }

  implicit class StacCollectionWithTiles(collection: StacCollection) {

    def addTilesLink(apiHost: String): StacCollection = {
      val encodedCollectionId = URLEncoder.encode(collection.id, StandardCharsets.UTF_8.toString)
      val tileLink = StacLink(
        s"$apiHost/collections/$encodedCollectionId/tiles",
        StacLinkType.VendorLinkType("tiles"),
        Some(`application/json`),
        Some("Tile URLs for Collection")
      )
      collection.copy(links = tileLink :: collection.links)
    }

    def maybeAddTilesLink(enableTiles: Boolean, apiHost: String) =
      if (enableTiles) addTilesLink(apiHost) else collection

    def updateLinksWithHost(apiConfig: ApiConfig) = {
      val updatedLinks = collection.links.map(_.addServerHost(apiConfig))
      collection.copy(links = updatedLinks)
    }
  }
} 
Example 2
Source File: TileRequest.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.datamodel

import eu.timepit.refined.types.numeric.NonNegInt
import eu.timepit.refined.types.string.NonEmptyString

import java.net.URLDecoder
import java.nio.charset.StandardCharsets

sealed trait TileMatrixRequest {
  val z: Int
  val x: Int
  val y: Int
  val collection: String

  def urlDecode(rawString: String): String =
    URLDecoder.decode(rawString, StandardCharsets.UTF_8.toString)
}

case class ItemRasterTileRequest(
    collectionRaw: String,
    itemRaw: String,
    z: Int,
    x: Int,
    y: Int,
    asset: String,
    redBandOption: Option[Int],
    greenBandOption: Option[Int],
    blueBandOption: Option[Int],
    upperQuantileOption: Option[Quantile],
    lowerQuantileOption: Option[Quantile],
    singleBand: Option[NonNegInt]
) extends TileMatrixRequest {

  val collection = urlDecode(collectionRaw)
  val item       = urlDecode(itemRaw)

  val redBand   = redBandOption.getOrElse(0)
  val greenBand = greenBandOption.getOrElse(1)
  val blueBand  = blueBandOption.getOrElse(2)

  val bands = Seq(redBand, greenBand, blueBand)

  // Because lists are 0 indexed and humans are 1 indexed we need to adjust
  val upperQuantile = upperQuantileOption.map(_.value).getOrElse(100) - 1
  val lowerQuantile = lowerQuantileOption.map(_.value).getOrElse(-1) + 1

  val zxy = (z, x, y)

}

case class MapboxVectorTileFootprintRequest(
    collectionRaw: String,
    z: Int,
    x: Int,
    y: Int,
    colorField: NonEmptyString
) extends TileMatrixRequest {
  val collection = urlDecode(collectionRaw)
} 
Example 3
Source File: TapirCodecRefinedTest.scala    From tapir   with Apache License 2.0 5 votes vote down vote up
package sttp.tapir.codec.refined

import eu.timepit.refined.api.Refined
import eu.timepit.refined.collection.NonEmpty
import eu.timepit.refined.numeric.{Greater, GreaterEqual, Less, LessEqual}
import eu.timepit.refined.string.{IPv4, MatchesRegex}
import eu.timepit.refined.types.string.NonEmptyString
import eu.timepit.refined.{W, refineMV, refineV}
import org.scalatest.{FlatSpec, Matchers}
import sttp.tapir.Codec.PlainCodec
import sttp.tapir.{DecodeResult, ValidationError, Validator}

class TapirCodecRefinedTest extends FlatSpec with Matchers with TapirCodecRefined {

  val nonEmptyStringCodec: PlainCodec[NonEmptyString] = implicitly[PlainCodec[NonEmptyString]]

  "Generated codec" should "return DecodResult.Invalid if subtype can't be refined with correct tapir validator if available" in {
    val expectedValidator: Validator[String] = Validator.minLength(1)
    nonEmptyStringCodec.decode("") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(validator, "", _))) if validator == expectedValidator =>
    }
  }

  it should "correctly delegate to raw parser and refine it" in {
    nonEmptyStringCodec.decode("vive le fromage") shouldBe DecodeResult.Value(refineMV[NonEmpty]("vive le fromage"))
  }

  it should "return DecodResult.Invalid if subtype can't be refined with derived tapir validator if non tapir validator available" in {
    type IPString = String Refined IPv4
    val IPStringCodec = implicitly[PlainCodec[IPString]]

    val expectedMsg = refineV[IPv4]("192.168.0.1000").left.get
    IPStringCodec.decode("192.168.0.1000") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(Validator.Custom(_, `expectedMsg`), "192.168.0.1000", _))) =>
    }
  }

  "Generated codec for MatchesRegex" should "use tapir Validator.Pattern" in {
    type VariableConstraint = MatchesRegex[W.`"[a-zA-Z][-a-zA-Z0-9_]*"`.T]
    type VariableString = String Refined VariableConstraint
    val identifierCodec = implicitly[PlainCodec[VariableString]]

    val expectedValidator: Validator[String] = Validator.pattern("[a-zA-Z][-a-zA-Z0-9_]*")
    identifierCodec.decode("-bad") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(validator, "-bad", _))) if validator == expectedValidator =>
    }
  }

  "Generated codec for Less" should "use tapir Validator.max" in {
    type IntConstraint = Less[W.`3`.T]
    type LimitedInt = Int Refined IntConstraint
    val limitedIntCodec = implicitly[PlainCodec[LimitedInt]]

    val expectedValidator: Validator[Int] = Validator.max(3, exclusive = true)
    limitedIntCodec.decode("3") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(validator, 3, _))) if validator == expectedValidator =>
    }
  }

  "Generated codec for LessEqual" should "use tapir Validator.max" in {
    type IntConstraint = LessEqual[W.`3`.T]
    type LimitedInt = Int Refined IntConstraint
    val limitedIntCodec = implicitly[PlainCodec[LimitedInt]]

    val expectedValidator: Validator[Int] = Validator.max(3)
    limitedIntCodec.decode("4") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(validator, 4, _))) if validator == expectedValidator =>
    }
  }

  "Generated codec for Greater" should "use tapir Validator.min" in {
    type IntConstraint = Greater[W.`3`.T]
    type LimitedInt = Int Refined IntConstraint
    val limitedIntCodec = implicitly[PlainCodec[LimitedInt]]

    val expectedValidator: Validator[Int] = Validator.min(3, exclusive = true)
    limitedIntCodec.decode("3") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(validator, 3, _))) if validator == expectedValidator =>
    }
  }

  "Generated codec for GreaterEqual" should "use tapir Validator.min" in {
    type IntConstraint = GreaterEqual[W.`3`.T]
    type LimitedInt = Int Refined IntConstraint
    val limitedIntCodec = implicitly[PlainCodec[LimitedInt]]

    val expectedValidator: Validator[Int] = Validator.min(3)
    limitedIntCodec.decode("2") should matchPattern {
      case DecodeResult.InvalidValue(List(ValidationError(validator, 2, _))) if validator == expectedValidator =>
    }
  }

  "Generated validator for Greater" should "use tapir Validator.min" in {
    type IntConstraint = Greater[W.`3`.T]
    type LimitedInt = Int Refined IntConstraint

    implicitly[Validator[LimitedInt]] should matchPattern {
      case Validator.Mapped(Validator.Min(3, true), _) =>
    }
  }
} 
Example 4
Source File: brand.scala    From pfps-shopping-cart   with Apache License 2.0 5 votes vote down vote up
package shop.domain

import eu.timepit.refined.types.string.NonEmptyString
import io.estatico.newtype.macros.newtype
import java.util.UUID
import scala.util.control.NoStackTrace

object brand {
  @newtype case class BrandId(value: UUID)

  @newtype case class BrandName(value: String) {
    def toBrand(brandId: BrandId): Brand =
      Brand(brandId, this)
  }

  @newtype case class BrandParam(value: NonEmptyString) {
    def toDomain: BrandName = BrandName(value.value.toLowerCase.capitalize)
  }

  case class Brand(uuid: BrandId, name: BrandName)

  case class InvalidBrand(value: String) extends NoStackTrace
} 
Example 5
Source File: item.scala    From pfps-shopping-cart   with Apache License 2.0 5 votes vote down vote up
package shop.domain

import eu.timepit.refined.api.Refined
import eu.timepit.refined.string.{ Uuid, ValidBigDecimal }
import eu.timepit.refined.types.string.NonEmptyString
import io.estatico.newtype.macros.newtype
import java.util.UUID
import shop.domain.brand._
import shop.domain.category._
import squants.market._

object item {

  @newtype case class ItemId(value: UUID)
  @newtype case class ItemName(value: String)
  @newtype case class ItemDescription(value: String)

  case class Item(
      uuid: ItemId,
      name: ItemName,
      description: ItemDescription,
      price: Money,
      brand: Brand,
      category: Category
  )

  // ----- Create item ------

  @newtype case class ItemNameParam(value: NonEmptyString)
  @newtype case class ItemDescriptionParam(value: NonEmptyString)
  @newtype case class PriceParam(value: String Refined ValidBigDecimal)

  case class CreateItemParam(
      name: ItemNameParam,
      description: ItemDescriptionParam,
      price: PriceParam,
      brandId: BrandId,
      categoryId: CategoryId
  ) {
    def toDomain: CreateItem =
      CreateItem(
        ItemName(name.value.value),
        ItemDescription(description.value.value),
        USD(BigDecimal(price.value.value)),
        brandId,
        categoryId
      )
  }

  case class CreateItem(
      name: ItemName,
      description: ItemDescription,
      price: Money,
      brandId: BrandId,
      categoryId: CategoryId
  )

  // ----- Update item ------

  @newtype case class ItemIdParam(value: String Refined Uuid)

  case class UpdateItemParam(
      id: ItemIdParam,
      price: PriceParam
  ) {
    def toDomain: UpdateItem =
      UpdateItem(
        ItemId(UUID.fromString(id.value.value)),
        USD(BigDecimal(price.value.value))
      )
  }

  case class UpdateItem(
      id: ItemId,
      price: Money
  )

} 
Example 6
Source File: auth.scala    From pfps-shopping-cart   with Apache License 2.0 5 votes vote down vote up
package shop.domain

import eu.timepit.refined.types.string.NonEmptyString
import io.circe._
import io.estatico.newtype.macros.newtype
import java.util.UUID
import javax.crypto.Cipher
import scala.util.control.NoStackTrace

object auth {

  @newtype case class UserId(value: UUID)
  @newtype case class UserName(value: String)
  @newtype case class Password(value: String)

  @newtype case class EncryptedPassword(value: String)

  @newtype case class EncryptCipher(value: Cipher)
  @newtype case class DecryptCipher(value: Cipher)

  // --------- user registration -----------

  @newtype case class UserNameParam(value: NonEmptyString) {
    def toDomain: UserName = UserName(value.value.toLowerCase)
  }

  @newtype case class PasswordParam(value: NonEmptyString) {
    def toDomain: Password = Password(value.value)
  }

  case class CreateUser(
      username: UserNameParam,
      password: PasswordParam
  )

  case class UserNameInUse(username: UserName) extends NoStackTrace
  case class InvalidUserOrPassword(username: UserName) extends NoStackTrace
  case object UnsupportedOperation extends NoStackTrace

  case object TokenNotFound extends NoStackTrace

  // --------- user login -----------

  case class LoginUser(
      username: UserNameParam,
      password: PasswordParam
  )

  // --------- admin auth -----------

  @newtype case class ClaimContent(uuid: UUID)

  object ClaimContent {
    implicit val jsonDecoder: Decoder[ClaimContent] =
      Decoder.forProduct1("uuid")(ClaimContent.apply)
  }

} 
Example 7
Source File: loader.scala    From pfps-shopping-cart   with Apache License 2.0 5 votes vote down vote up
package shop.config

import cats.effect._
import cats.implicits._
import ciris._
import ciris.refined._
import environments._
import environments.AppEnvironment._
import eu.timepit.refined.auto._
import eu.timepit.refined.cats._
import eu.timepit.refined.types.string.NonEmptyString
import scala.concurrent.duration._
import shop.config.data._

object load {

  // Ciris promotes configuration as code
  def apply[F[_]: Async: ContextShift]: F[AppConfig] =
    env("SC_APP_ENV")
      .as[AppEnvironment]
      .flatMap {
        case Test =>
          default(
            redisUri = RedisURI("redis://localhost"),
            paymentUri = PaymentURI("https://payments.free.beeceptor.com")
          )
        case Prod =>
          default(
            redisUri = RedisURI("redis://10.123.154.176"),
            paymentUri = PaymentURI("https://payments.net/api")
          )
      }
      .load[F]

  private def default(
      redisUri: RedisURI,
      paymentUri: PaymentURI
  ): ConfigValue[AppConfig] =
    (
      env("SC_JWT_SECRET_KEY").as[NonEmptyString].secret,
      env("SC_JWT_CLAIM").as[NonEmptyString].secret,
      env("SC_ACCESS_TOKEN_SECRET_KEY").as[NonEmptyString].secret,
      env("SC_ADMIN_USER_TOKEN").as[NonEmptyString].secret,
      env("SC_PASSWORD_SALT").as[NonEmptyString].secret
    ).parMapN { (secretKey, claimStr, tokenKey, adminToken, salt) =>
      AppConfig(
        AdminJwtConfig(
          JwtSecretKeyConfig(secretKey),
          JwtClaimConfig(claimStr),
          AdminUserTokenConfig(adminToken)
        ),
        JwtSecretKeyConfig(tokenKey),
        PasswordSalt(salt),
        TokenExpiration(30.minutes),
        ShoppingCartExpiration(30.minutes),
        CheckoutConfig(
          retriesLimit = 3,
          retriesBackoff = 10.milliseconds
        ),
        PaymentConfig(paymentUri),
        HttpClientConfig(
          connectTimeout = 2.seconds,
          requestTimeout = 2.seconds
        ),
        PostgreSQLConfig(
          host = "localhost",
          port = 5432,
          user = "postgres",
          database = "store",
          max = 10
        ),
        RedisConfig(redisUri),
        HttpServerConfig(
          host = "0.0.0.0",
          port = 8080
        )
      )
    }

} 
Example 8
Source File: data.scala    From pfps-shopping-cart   with Apache License 2.0 5 votes vote down vote up
package shop.config

import ciris._
import eu.timepit.refined.types.net.UserPortNumber
import eu.timepit.refined.types.numeric.PosInt
import eu.timepit.refined.types.string.NonEmptyString
import io.estatico.newtype.macros.newtype
import scala.concurrent.duration._

object data {

  @newtype case class AdminUserTokenConfig(value: Secret[NonEmptyString])
  @newtype case class JwtSecretKeyConfig(value: Secret[NonEmptyString])
  @newtype case class JwtClaimConfig(value: Secret[NonEmptyString])
  @newtype case class TokenExpiration(value: FiniteDuration)

  @newtype case class PasswordSalt(value: Secret[NonEmptyString])

  @newtype case class ShoppingCartExpiration(value: FiniteDuration)

  case class CheckoutConfig(
      retriesLimit: PosInt,
      retriesBackoff: FiniteDuration
  )

  case class AppConfig(
      adminJwtConfig: AdminJwtConfig,
      tokenConfig: JwtSecretKeyConfig,
      passwordSalt: PasswordSalt,
      tokenExpiration: TokenExpiration,
      cartExpiration: ShoppingCartExpiration,
      checkoutConfig: CheckoutConfig,
      paymentConfig: PaymentConfig,
      httpClientConfig: HttpClientConfig,
      postgreSQL: PostgreSQLConfig,
      redis: RedisConfig,
      httpServerConfig: HttpServerConfig
  )

  case class AdminJwtConfig(
      secretKey: JwtSecretKeyConfig,
      claimStr: JwtClaimConfig,
      adminToken: AdminUserTokenConfig
  )

  case class PostgreSQLConfig(
      host: NonEmptyString,
      port: UserPortNumber,
      user: NonEmptyString,
      database: NonEmptyString,
      max: PosInt
  )

  @newtype case class RedisURI(value: NonEmptyString)
  @newtype case class RedisConfig(uri: RedisURI)

  @newtype case class PaymentURI(value: NonEmptyString)
  @newtype case class PaymentConfig(uri: PaymentURI)

  case class HttpServerConfig(
      host: NonEmptyString,
      port: UserPortNumber
  )

  case class HttpClientConfig(
      connectTimeout: FiniteDuration,
      requestTimeout: FiniteDuration
  )

} 
Example 9
Source File: types.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc

import eu.timepit.refined.types.string.NonEmptyString
import org.scalacheck.Arbitrary
import org.scalacheck.Arbitrary.arbitrary

final case class Foo(x: Int)
object Foo {
  implicit final val fooRead: Bulk ==> Foo = Read.instance {
    case Bulk(ToInt(i)) => Right(Foo(i))
    case Bulk(other)    => Left(RESPDecErr(s"Boom: $other"))
  }
}

final case class Bar(x: String)

final case class Baz(f1: Int, f2: String)
object Baz {
  implicit final val bazArb: Arbitrary[Baz] = Arbitrary {
    for {
      i <- arbitrary[Int]
      s <- arbitrary[String]
    } yield Baz(i, s)
  }
}

private[laserdisc] sealed trait ProtocolEncoded extends Product with Serializable { def encoded: String }
private[laserdisc] final case class ArrEncoded(v: List[ProtocolEncoded]) extends ProtocolEncoded {
  def encoded: String = s"*${v.size}$CRLF${v.map(_.encoded).mkString}"
}
private[laserdisc] final case class EmptyArrEncoded() extends ProtocolEncoded {
  def encoded: String = s"*0$CRLF"
}
private[laserdisc] final case class NullArrEncoded() extends ProtocolEncoded {
  def encoded: String = s"*-1$CRLF"
}
private[laserdisc] final case class EmptyBulkEncoded() extends ProtocolEncoded {
  def encoded: String = s"$$0$CRLF$CRLF"
}
private[laserdisc] final case class BulkEncoded(v: NonEmptyString) extends ProtocolEncoded {
  def encoded: String = s"$$${v.value.getBytes.length}$CRLF${v.value}$CRLF"
}
private[laserdisc] final case class NullBulkEncoded() extends ProtocolEncoded {
  def encoded: String = s"$$-1$CRLF"
}
private[laserdisc] final case class NumEncoded(v: Long) extends ProtocolEncoded {
  def encoded: String = s":$v$CRLF"
}
private[laserdisc] final case class StrEncoded(v: String) extends ProtocolEncoded {
  def encoded: String = s"+$v$CRLF"
}
private[laserdisc] final case class ErrEncoded(v: NonEmptyString) extends ProtocolEncoded {
  def encoded: String = s"-${v.value}$CRLF"
} 
Example 10
Source File: RESPFrameBench.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
import scodec.bits.BitVector
import eu.timepit.refined.types.string.NonEmptyString
import java.nio.ByteBuffer

import laserdisc.RESPFrameFixture
import org.openjdk.jmh.infra.Blackhole

@State(Scope.Benchmark)
class RESPFrameBench extends RESPFrameFixture {

  val mixedNoArr = bytesOf(mixedNoArrList)
  val arrOneLevel = bytesOf(arrOneLevelList)
  val arrFiveLevels = bytesOf(arrFiveLevelsList)

  val empty = BitVector.empty.toByteBuffer
  val mixedNoArrFull = BitVector(mixedNoArr).toByteBuffer
  val arrOneLevelFull = BitVector(arrOneLevel).toByteBuffer
  val arrFiveLevelsFull = BitVector(arrFiveLevels).toByteBuffer

  @Benchmark def frameOfFullBaseline(bh: Blackhole)= {
    val frame = EmptyFrame.append(empty)
    bh.consume(frame)
  }
  @Benchmark def frameOfMixedNoArrFull(bh: Blackhole) = {
    val frame = EmptyFrame.append(mixedNoArrFull)
    bh.consume(frame)
  }
  @Benchmark def frameOfMixedArrOneLevelFull(bh: Blackhole) = {
    val frame = EmptyFrame.append(arrOneLevelFull)
    bh.consume(frame)
  }
  @Benchmark def frameOfMixedArrFiveLevelsFull(bh: Blackhole) = {
    val frame = EmptyFrame.append(arrFiveLevelsFull)
    bh.consume(frame)
  }

  val mixedNoArrSmallChunkBuffers    = groupInChunks(mixedNoArr, 128)
  val arrOneLevelSmallChunkBuffers   = groupInChunks(arrOneLevel, 128)
  val arrFiveLevelsSmallChunkBuffers = groupInChunks(arrFiveLevels, 128)

  @Benchmark def frameOfChunkedBaseline(bh: Blackhole)= {
    val frames = appendChunks(Iterator.empty[BitVector])
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedShortMixedNoArr(bh: Blackhole)= {
    val frames = appendChunks(mixedNoArrSmallChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedShortArrOneLevel(bh: Blackhole)   = {
    val frames = appendChunks(arrOneLevelSmallChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedShortArrFiveLevels(bh: Blackhole) = {
    val frames = appendChunks(arrFiveLevelsSmallChunkBuffers)
    bh.consume(frames)
  }

  val mixedNoArrBigChunkBuffers    = groupInChunks(mixedNoArr, 1024)
  val arrOneLevelBigChunkBuffers   = groupInChunks(arrOneLevel, 1024)
  val arrFiveLevelsBigChunkBuffers = groupInChunks(arrFiveLevels, 1024)

  @Benchmark def frameOfChunkedLongMixedNoArr(bh: Blackhole)    = {
    val frames = appendChunks(mixedNoArrBigChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedLongArrOneLevel(bh: Blackhole)   = {
    val frames = appendChunks(arrOneLevelBigChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedLongArrFiveLevels(bh: Blackhole) = {
    val frames = appendChunks(arrFiveLevelsBigChunkBuffers)
    bh.consume(frames)
  }
} 
Example 11
Source File: Config.scala    From tamer   with MIT License 5 votes vote down vote up
package tamer
package config

import cats.implicits._
import ciris.{ConfigError => CirisConfigError, _}
import ciris.refined._
import eu.timepit.refined.auto._
import eu.timepit.refined.types.numeric.PosInt
import eu.timepit.refined.types.string.NonEmptyString
import zio.{IO, Task, ZIO}
import zio.interop.catz._
import zio.macros.annotation.accessible

import scala.concurrent.duration.FiniteDuration

final case class DbConfig(driver: NonEmptyString, uri: UriString, username: NonEmptyString, password: Password)
final case class QueryConfig(fetchChunkSize: PosInt)
final case class KafkaSinkConfig(topic: NonEmptyString)
final case class KafkaStateConfig(topic: NonEmptyString, groupId: NonEmptyString, clientId: NonEmptyString)
final case class KafkaConfig(
    brokers: HostList,
    schemaRegistryUrl: UrlString,
    closeTimeout: FiniteDuration,
    bufferSize: PosInt,
    sink: KafkaSinkConfig,
    state: KafkaStateConfig
)
final case class TamerConfig(db: DbConfig, query: QueryConfig, kafka: KafkaConfig)

@accessible(">") trait Config extends Serializable {
  val config: Config.Service[Any]
}

object Config {
  trait Service[R] {
    val load: ZIO[R, ConfigError, TamerConfig]
  }

  trait Live extends Config {
    private[this] implicit final val hostListConfigDecoder: ConfigDecoder[String, HostList] =
      ConfigDecoder.identity[String].map(_.split(",").toList.map(_.trim)).mapEither(ConfigDecoder[List[String], HostList].decode)

    override final val config: Service[Any] = new Service[Any] {
      private val dbConfig = (
        env("DATABASE_DRIVER").as[NonEmptyString],
        env("DATABASE_URL").as[UriString],
        env("DATABASE_USERNAME").as[NonEmptyString],
        env("DATABASE_PASSWORD").as[Password].redacted
      ).parMapN(DbConfig)

      private val queryConfig = env("QUERY_FETCH_CHUNK_SIZE").as[PosInt].map(QueryConfig)

      private val kafkaSinkConfig = env("KAFKA_SINK_TOPIC").as[NonEmptyString].map(KafkaSinkConfig)
      private val kafkaStateConfig = (
        env("KAFKA_STATE_TOPIC").as[NonEmptyString],
        env("KAFKA_STATE_GROUP_ID").as[NonEmptyString],
        env("KAFKA_STATE_CLIENT_ID").as[NonEmptyString]
      ).parMapN(KafkaStateConfig)
      private val kafkaConfig = (
        env("KAFKA_BROKERS").as[HostList],
        env("KAFKA_SCHEMA_REGISTRY_URL").as[UrlString],
        env("KAFKA_CLOSE_TIMEOUT").as[FiniteDuration],
        env("KAFKA_BUFFER_SIZE").as[PosInt],
        kafkaSinkConfig,
        kafkaStateConfig
      ).parMapN(KafkaConfig)

      val tamerConfig: ConfigValue[TamerConfig] = (dbConfig, queryConfig, kafkaConfig).parMapN((db, query, kafka) => TamerConfig(db, query, kafka))

      override final val load: IO[ConfigError, TamerConfig] =
        tamerConfig.load[Task].refineToOrDie[CirisConfigError].mapError(ce => ConfigError(ce.redacted.show))
    }
  }

  object Live extends Live
} 
Example 12
Source File: RefinedSupportTest.scala    From diffx   with Apache License 2.0 5 votes vote down vote up
package com.softwaremill.diffx.refined

import com.softwaremill.diffx.{DiffResultObject, DiffResultString, DiffResultValue, Identical, _}
import eu.timepit.refined.types.numeric.PosInt
import eu.timepit.refined.auto._
import eu.timepit.refined.types.string.NonEmptyString
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class RefinedSupportTest extends AnyFlatSpec with Matchers {
  it should "work for refined types" in {
    val testData1 = TestData(1, "foo")
    val testData2 = TestData(1, "bar")
    compare(testData1, testData2) shouldBe DiffResultObject(
      "TestData",
      Map("posInt" -> Identical(1), "nonEmptyString" -> DiffResultString(List(DiffResultValue("foo", "bar"))))
    )
  }
}

case class TestData(posInt: PosInt, nonEmptyString: NonEmptyString) 
Example 13
Source File: config.scala    From frdomain-extras   with Apache License 2.0 5 votes vote down vote up
package frdomain.ch6.domain
package config

import ciris._
import eu.timepit.refined.types.net.UserPortNumber
import eu.timepit.refined.types.numeric.PosInt
import eu.timepit.refined.types.string.NonEmptyString

object config {
  case class AppConfig (
    postgreSQL: PostgreSQLConfig
  )

  case class PostgreSQLConfig(
      host: NonEmptyString,
      port: UserPortNumber,
      user: NonEmptyString,
      database: NonEmptyString,
      max: PosInt
  )
} 
Example 14
Source File: loader.scala    From frdomain-extras   with Apache License 2.0 5 votes vote down vote up
package frdomain.ch6.domain
package config

import cats.effect._
import cats.implicits._
import ciris._
import ciris.refined._
import environments._
import environments.AppEnvironment._
import eu.timepit.refined.auto._
import eu.timepit.refined.cats._
import eu.timepit.refined.types.string.NonEmptyString
import config._

object load {
  
  def apply[F[_]: Async: ContextShift]: F[AppConfig] =
    env("BANKING_APP_ENV")
      .as[AppEnvironment]
      .default(Prod)
      .flatMap {
        case Test => default
        case Prod => default
      }
      .load[F]

  private def default: ConfigValue[AppConfig] =
    (
      env("DATABASE_USER").as[NonEmptyString].default("postgres"),
      env("DATABASE_NAME").as[NonEmptyString].default("banking"),
    ).parMapN { (dbuser, dbname) =>
      AppConfig(
        PostgreSQLConfig(
          host = "localhost",
          port = 5432,
          user = dbuser,
          database = dbname,
          max = 10
        )
      )
    }
} 
Example 15
Source File: ValidationSpec.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.validation

import cats.implicits._
import com.azavea.stac4s.StacItem
import com.azavea.stac4s.syntax._
import com.azavea.stac4s.testing._
import eu.timepit.refined.types.string.NonEmptyString
import org.specs2.{ScalaCheck, Specification}

class ValidationSpec extends Specification with ScalaCheck {

  def is = s2"""
  This specification verifies that the Validation extension behaves sensibly

  The validation extension should:
    - report all the extensions it tries to validate   $validateSeveralExpectation
    - accumulate errors from checked extensions        $accumulateErrorsExpectation
"""

  def validateSeveralExpectation = prop { (item: StacItem) =>
    val validate = getItemValidator(List("label", "layer"))
    val test = validate(item)
      .getExtensionFields[ValidationExtension]
      .toEither
      .right
      .get
      .attemptedExtensions
      .toList
      .toSet
      .map { (s: NonEmptyString) => s.value }
    val expectation = Set(Label, Layer) map { _.repr }
    test should beTypedEqualTo(expectation)
  }

  def accumulateErrorsExpectation = prop { (item: StacItem) =>
    val validateLabel    = getItemValidator(List("label"))
    val validateLayer    = getItemValidator(List("layer"))
    val combinedValidate = getItemValidator(List("layer", "label"))

    val labelValidated    = validateLabel(item)
    val layerValidated    = validateLayer(item)
    val combinedValidated = combinedValidate(item)

    val test = (labelValidated.getExtensionFields[ValidationExtension] |+| layerValidated
      .getExtensionFields[ValidationExtension]).toEither.right.get.errors.toSet

    val expectation = combinedValidated
      .getExtensionFields[ValidationExtension]
      .toEither
      .right
      .get
      .errors
      .toSet

    test should beTypedEqualTo(expectation)
  }

} 
Example 16
Source File: RefinedSpec.scala    From refined   with MIT License 5 votes vote down vote up
package eu.timepit.refined

import eu.timepit.refined.TestUtils.wellTyped
import eu.timepit.refined.api.Refined
import eu.timepit.refined.collection.NonEmpty
import eu.timepit.refined.types.string.NonEmptyString
import org.scalacheck.Prop._
import org.scalacheck.Properties
import shapeless.test.illTyped

class RefinedSpec extends Properties("Refined") {

  property("apply") = wellTyped {
    illTyped(
      """ val x: NonEmptyString = Refined("") """,
      "eu.timepit.refined.api.Refined.type does not take parameters"
    )
  }

  property("copy") = wellTyped {
    val x: NonEmptyString = refineMV[NonEmpty]("abc")
    illTyped(
      """ x.copy("") """,
      "value copy is not a member of eu.timepit.refined.types.string.NonEmptyString"
    )
  }

  property("equals") = secure {
    (Refined.unsafeApply(1) ?= Refined.unsafeApply(1)) &&
    !Refined.unsafeApply(1).equals(1)
  }

  property("hashCode") = forAll { i: Int => Refined.unsafeApply(i).hashCode() ?= i.hashCode }

  property("unapply") = secure {
    val x: NonEmptyString = refineMV("Hi")
    val Refined(s) = x
    s ?= x.value
  }

  property("unapply in pattern matching") = secure {
    val x: NonEmptyString = refineMV("abc")
    x match {
      case Refined("abc") => true
      case _              => false
    }
  }
} 
Example 17
Source File: Link.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.datamodel

import com.azavea.stac4s.{StacLinkType, StacMediaType}
import eu.timepit.refined.types.string.NonEmptyString
import io.circe.Encoder
import io.circe.generic.semiauto._

case class Link(
    href: NonEmptyString,
    rel: StacLinkType,
    _type: Option[StacMediaType],
    title: Option[NonEmptyString]
)

object Link {

  implicit val encStacLink: Encoder[Link] = Encoder.forProduct4(
    "href",
    "rel",
    "type",
    "title"
  )(link => (link.href, link.rel, link._type, link.title))

  implicit val decoderLink = deriveDecoder[Link]
} 
Example 18
Source File: PagingLinkExtension.scala.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.paging

import com.azavea.franklin.database.SearchFilters
import com.azavea.stac4s.extensions.LinkExtension
import eu.timepit.refined.types.string.NonEmptyString
import io.circe.generic.semiauto._
import io.circe.refined._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json}

// https://github.com/radiantearth/stac-api-spec/blob/7a6e12868113c94b17dead8989f49d978d5dd865/api-spec.md#paging-extension
// the method for us is always POST, since otherwise we toss the params in the query string
// and don't use this
final case class PagingLinkExtension(
    headers: Map[NonEmptyString, String],
    body: SearchFilters,
    merge: Boolean
)

object PagingLinkExtension {
  implicit val decPagingLinkExtension: Decoder[PagingLinkExtension] = deriveDecoder

  implicit val encPagingLinkExtension: Encoder.AsObject[PagingLinkExtension] = Encoder
    .AsObject[Map[String, Json]]
    .contramapObject((linkExtensionFields: PagingLinkExtension) =>
      Map(
        "method"  -> "POST".asJson,
        "headers" -> linkExtensionFields.headers.asJson,
        "body"    -> linkExtensionFields.body.asJson,
        "merge"   -> linkExtensionFields.merge.asJson
      )
    )

  implicit val linkExtensionPagingLinkExtension: LinkExtension[PagingLinkExtension] =
    LinkExtension.instance
} 
Example 19
Source File: LinkValidator.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.validation

import com.azavea.stac4s.StacLink
import com.azavea.stac4s.StacLinkType
import com.azavea.stac4s.extensions.LinkExtension
import com.azavea.stac4s.extensions.label.LabelLinkExtension
import com.azavea.stac4s.syntax._
import eu.timepit.refined.auto._
import eu.timepit.refined.types.string.NonEmptyString

trait LinkValidator[T] {
  def validate(link: StacLink): StacLink
}

object LinkValidator {

  def apply[T](implicit ev: LinkValidator[T]) = ev

  def identity[T] = new LinkValidator[T] {
    def validate(link: StacLink): StacLink = link
  }

  def instance[T: LinkExtension](name: NonEmptyString) = new LinkValidator[T] {

    def validate(link: StacLink) = {
      val extensionResult     = link.getExtensionFields[T]
      val validationExtension = ValidationExtension.fromResult(extensionResult, name)
      link.addExtensionFields(validationExtension)
    }
  }

  // It will often be the case that links only need to be checked for an extension
  // under certain conditions. For example, the label extension only modifies the
  // link with the relation "source". As long as the information required to make
  // this decision is local to the link, it can be encoded in this simple way.
  def when[T: LinkExtension](
      predicate: StacLink => Boolean,
      name: NonEmptyString
  ): LinkValidator[T] = new LinkValidator[T] {

    def validate(link: StacLink) = {
      if (predicate(link)) {
        instance(name).validate(link)
      } else {
        identity[T].validate(link)
      }
    }
  }

  implicit val labelLinkValidator: LinkValidator[LabelLinkExtension] =
    when(_.rel == StacLinkType.Source, "label")

} 
Example 20
Source File: ItemValidator.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.validation

import cats.syntax.semigroup._
import com.azavea.stac4s.StacItem
import com.azavea.stac4s.extensions.ItemExtension
import com.azavea.stac4s.extensions.eo.EOItemExtension
import com.azavea.stac4s.extensions.label.LabelItemExtension
import com.azavea.stac4s.extensions.layer.LayerItemExtension
import com.azavea.stac4s.syntax._
import eu.timepit.refined.auto._
import eu.timepit.refined.types.string.NonEmptyString

trait ItemValidator[T] {
  def validate(item: StacItem): StacItem
}

object ItemValidator {

  def apply[T](implicit ev: ItemValidator[T]) = ev

  def instance[T: ItemExtension](name: NonEmptyString) = new ItemValidator[T] {

    def validate(item: StacItem) = {
      val extensionResult     = item.getExtensionFields[T]
      val validationExtension = ValidationExtension.fromResult(extensionResult, name)
      val existingValidation  = item.getExtensionFields[ValidationExtension]
      item.addExtensionFields(existingValidation map { _ |+| validationExtension } getOrElse {
        validationExtension
      })
    }
  }

  implicit val labelItemValidator: ItemValidator[LabelItemExtension] = instance("label")
  implicit val layerItemValidator: ItemValidator[LayerItemExtension] = instance("layer")
  implicit val eoItemValidator: ItemValidator[EOItemExtension]       = instance("eo")

} 
Example 21
Source File: ValidationExtension.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.validation

import cats.data.NonEmptyList
import cats.data.Validated.{Invalid, Valid}
import cats.kernel.Semigroup
import com.azavea.stac4s.extensions.ItemAssetExtension
import com.azavea.stac4s.extensions.{ExtensionResult, ItemExtension, LinkExtension}
import eu.timepit.refined.types.string.NonEmptyString
import io.circe._
import io.circe.refined._
import io.circe.syntax._

final case class ValidationExtension(
    attemptedExtensions: NonEmptyList[NonEmptyString],
    errors: List[NonEmptyString]
)

object ValidationExtension {

  implicit val decValidationExtension: Decoder[ValidationExtension] = Decoder.forProduct2(
    "validation:attemptedExtensions",
    "validation:errors"
  )((extensions: NonEmptyList[NonEmptyString], errors: List[NonEmptyString]) =>
    ValidationExtension(extensions, errors)
  )

  implicit val encValidationExtension: Encoder.AsObject[ValidationExtension] = Encoder
    .AsObject[Map[String, Json]]
    .contramapObject((validationExtensionFields: ValidationExtension) =>
      Map(
        "validation:attemptedExtensions" -> validationExtensionFields.attemptedExtensions.asJson,
        "validation:errors"              -> validationExtensionFields.errors.asJson
      )
    )

  implicit val validationExtensionItemExtension: ItemExtension[ValidationExtension] =
    ItemExtension.instance

  implicit val validationExtensionLinkExtension: LinkExtension[ValidationExtension] =
    LinkExtension.instance

  implicit val validationExtensionAssetExtension: ItemAssetExtension[ValidationExtension] =
    ItemAssetExtension.instance

  implicit val semigroupValidationExtension: Semigroup[ValidationExtension] =
    new Semigroup[ValidationExtension] {

      def combine(x: ValidationExtension, y: ValidationExtension): ValidationExtension = {
        ValidationExtension(
          x.attemptedExtensions.concat(y.attemptedExtensions.toList),
          x.errors ++ y.errors
        )
      }
    }

  def success(name: NonEmptyString) = ValidationExtension(
    NonEmptyList.of(name),
    Nil
  )

  def failure(name: NonEmptyString, errors: List[DecodingFailure]) =
    ValidationExtension(NonEmptyList.of(name), errors map { (err: DecodingFailure) =>
      NonEmptyString.from(CursorOp.opsToPath(err.history))
    } collect {
      case Right(v) => v
    })

  def fromResult[T](result: ExtensionResult[T], name: NonEmptyString) = result match {
    case Invalid(errs) =>
      failure(name, errs collect {
        case e: DecodingFailure => e
      })
    case Valid(_) =>
      success(name)
  }
} 
Example 22
Source File: SearchService.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.api.services

import cats.effect._
import cats.implicits._
import com.azavea.franklin.api.endpoints.SearchEndpoints
import com.azavea.franklin.api.implicits._
import com.azavea.franklin.database.{SearchFilters, StacItemDao}
import com.azavea.franklin.datamodel.SearchMethod
import doobie.implicits._
import doobie.util.transactor.Transactor
import eu.timepit.refined.types.numeric.NonNegInt
import eu.timepit.refined.types.string.NonEmptyString
import io.circe._
import io.circe.syntax._
import org.http4s._
import org.http4s.dsl.Http4sDsl
import sttp.tapir.server.http4s._

class SearchService[F[_]: Sync](
    apiHost: NonEmptyString,
    defaultLimit: NonNegInt,
    enableTiles: Boolean,
    xa: Transactor[F]
)(
    implicit contextShift: ContextShift[F]
) extends Http4sDsl[F] {

  def search(searchFilters: SearchFilters, searchMethod: SearchMethod): F[Either[Unit, Json]] = {
    for {
      searchResult <- StacItemDao
        .getSearchResult(
          searchFilters,
          searchFilters.limit getOrElse defaultLimit,
          apiHost,
          searchMethod
        )
        .transact(xa)
    } yield {
      val updatedFeatures = searchResult.features.map { item =>
        (item.collection, enableTiles) match {
          case (Some(collectionId), true) => item.addTilesLink(apiHost.value, collectionId, item.id)
          case _                          => item
        }
      }
      Either.right(searchResult.copy(features = updatedFeatures).asJson)
    }
  }

  val routes: HttpRoutes[F] =
    SearchEndpoints.searchGet.toRoutes(searchFilters => search(searchFilters, SearchMethod.Get)) <+> SearchEndpoints.searchPost
      .toRoutes {
        case searchFilters => search(searchFilters, SearchMethod.Post)
      }
} 
Example 23
Source File: LandingPageService.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.api.services

import cats._
import cats.effect._
import cats.implicits._
import com.azavea.franklin.api.commands.ApiConfig
import com.azavea.franklin.api.endpoints.LandingPageEndpoints
import com.azavea.franklin.api.implicits._
import com.azavea.franklin.datamodel.{LandingPage, Link, Conformance => FranklinConformance}
import com.azavea.stac4s.StacLinkType
import com.azavea.stac4s._
import eu.timepit.refined.auto._
import eu.timepit.refined.types.string.NonEmptyString
import io.circe._
import io.circe.syntax._
import org.http4s._
import org.http4s.dsl.Http4sDsl
import sttp.tapir.server.http4s._

class LandingPageService[F[_]: Sync](apiConfig: ApiConfig)(implicit contextShift: ContextShift[F])
    extends Http4sDsl[F] {

  val links = List(
    Link(
      apiConfig.apiHost,
      StacLinkType.Self,
      Some(`application/json`),
      Some("Franklin Powered Catalog")
    ),
    Link(
      apiConfig.apiHost + "/open-api/spec.yaml",
      StacLinkType.ServiceDesc,
      Some(VendorMediaType("application/vnd.oai.openapi+json;version=3.0")),
      Some("Open API 3 Documentation")
    ),
    Link(
      apiConfig.apiHost + "/conformance",
      StacLinkType.Conformance,
      Some(`application/json`),
      None
    ),
    Link(
      apiConfig.apiHost + "/collections",
      StacLinkType.Data,
      Some(`application/json`),
      Some("Collections Listing")
    ),
    Link(
      apiConfig.apiHost + "/search",
      StacLinkType.Data,
      Some(`application/geo+json`),
      Some("Franklin Powered STAC")
    )
  )

  def landingPage(): F[Either[Unit, Json]] = {
    Applicative[F].pure {
      val title: NonEmptyString = "Franklin Powered OGC API - Features and STAC web service"
      val description: NonEmptyString =
        "Web service powered by [Franklin](https://github.com/azavea/franklin)"
      Right(LandingPage(title, description, links).asJson)
    }
  }

  def conformancePage(): F[Either[Unit, Json]] = {
    Applicative[F].pure {
      val uriList: List[NonEmptyString] = List(
        "http://www.opengis.net/spec/ogcapi-features-1/1.0/req/core",
        "http://www.opengis.net/spec/ogcapi-features-1/1.0/req/oas30",
        "http://www.opengis.net/spec/ogcapi-features-1/1.0/req/geojson"
      )
      Right(FranklinConformance(uriList).asJson)
    }
  }

  val routes: HttpRoutes[F] =
    LandingPageEndpoints.landingPageEndpoint.toRoutes(_ => landingPage()) <+>
      LandingPageEndpoints.conformanceEndpoint.toRoutes(_ => conformancePage())
} 
Example 24
Source File: TileEndpoints.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.api.endpoints

import com.azavea.franklin.datamodel.{
  ItemRasterTileRequest,
  MapboxVectorTileFootprintRequest,
  Quantile
}
import com.azavea.franklin.error.NotFound
import eu.timepit.refined.types.numeric.NonNegInt
import eu.timepit.refined.types.string.NonEmptyString
import io.circe.Json
import sttp.model.StatusCode.{NotFound => NF}
import sttp.tapir._
import sttp.tapir.codec.refined._
import sttp.tapir.json.circe._

class TileEndpoints(enableTiles: Boolean) {

  val basePath = "tiles" / "collections"
  val zxyPath  = path[Int] / path[Int] / path[Int]

  val itemRasterTilePath: EndpointInput[(String, String, Int, Int, Int)] =
    (basePath / path[String] / "items" / path[String] / "WebMercatorQuad" / zxyPath)

  val collectionFootprintTilePath: EndpointInput[(String, Int, Int, Int)] =
    (basePath / path[String] / "footprint" / "WebMercatorQuad" / zxyPath)

  val collectionFootprintTileParameters: EndpointInput[(String, Int, Int, Int, NonEmptyString)] =
    collectionFootprintTilePath.and(query[NonEmptyString]("colorField"))

  val collectionFootprintTileJsonPath: EndpointInput[String] =
    (basePath / path[String] / "footprint" / "tile-json")

  val itemRasterTileParameters: EndpointInput[ItemRasterTileRequest] =
    itemRasterTilePath
      .and(query[String]("asset"))
      .and(query[Option[Int]]("redBand"))
      .and(query[Option[Int]]("greenBand"))
      .and(query[Option[Int]]("blueBand"))
      .and(query[Option[Quantile]]("upperQuantile"))
      .and(query[Option[Quantile]]("lowerQuantile"))
      .and(query[Option[NonNegInt]]("singleBand"))
      .mapTo(ItemRasterTileRequest)

  val itemRasterTileEndpoint: Endpoint[ItemRasterTileRequest, NotFound, Array[Byte], Nothing] =
    endpoint.get
      .in(itemRasterTileParameters)
      .out(rawBinaryBody[Array[Byte]])
      .out(header("content-type", "image/png"))
      .errorOut(oneOf(statusMapping(NF, jsonBody[NotFound].description("not found"))))
      .description("Raster Tile endpoint for Collection Item")
      .name("collectionItemTiles")

  val collectionFootprintTileEndpoint
      : Endpoint[MapboxVectorTileFootprintRequest, NotFound, Array[Byte], Nothing] =
    endpoint.get
      .in(collectionFootprintTileParameters.mapTo(MapboxVectorTileFootprintRequest))
      .out(rawBinaryBody[Array[Byte]])
      .out(header("content-type", "application/vnd.mapbox-vector-tile"))
      .errorOut(oneOf(statusMapping(NF, jsonBody[NotFound].description("not found"))))
      .description("MVT endpoint for a collection's footprint")
      .name("collectionFootprintTiles")

  val collectionFootprintTileJson: Endpoint[String, NotFound, Json, Nothing] =
    endpoint.get
      .in(collectionFootprintTileJsonPath)
      .out(jsonBody[Json])
      .errorOut(oneOf(statusMapping(NF, jsonBody[NotFound].description("not found"))))
      .description("TileJSON representation of this collection's footprint tiles")
      .name("collectionFootprintTileJSON")

  val endpoints = enableTiles match {
    case true =>
      List(itemRasterTileEndpoint, collectionFootprintTileEndpoint, collectionFootprintTileJson)
    case _ => List.empty
  }
} 
Example 25
Source File: ApiConfig.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.api.commands

import eu.timepit.refined.types.numeric.{NonNegInt, PosInt}
import eu.timepit.refined.types.string.NonEmptyString

case class ApiConfig(
    publicPort: PosInt,
    internalPort: PosInt,
    host: String,
    scheme: String,
    defaultLimit: NonNegInt,
    enableTransactions: Boolean,
    enableTiles: Boolean
) {

  val apiHost: NonEmptyString = getHost(publicPort, host, scheme)

} 
Example 26
Source File: SemVerTest.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.data

import eu.timepit.refined.types.numeric.NonNegBigInt
import eu.timepit.refined.types.string.NonEmptyString
import org.scalasteward.core.data.SemVer.Change
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

class SemVerTest extends AnyFunSuite with Matchers {
  implicit val toNonNegBigInt: Int => NonNegBigInt =
    i => NonNegBigInt.unsafeFrom(BigInt(i))

  implicit val toNonEmptyString: String => NonEmptyString =
    NonEmptyString.unsafeFrom

  test("parse: simple examples") {
    SemVer.parse("1.2.3") shouldBe Some(SemVer(1, 2, 3, None, None))
    SemVer.parse("0.0.0") shouldBe Some(SemVer(0, 0, 0, None, None))
    SemVer.parse("123.456.789") shouldBe Some(SemVer(123, 456, 789, None, None))
  }

  test("parse: with pre-release identifier") {
    SemVer.parse("1.0.0-SNAP5") shouldBe Some(SemVer(1, 0, 0, Some("SNAP5"), None))
    SemVer.parse("9.10.100-0.3.7") shouldBe Some(SemVer(9, 10, 100, Some("0.3.7"), None))
  }

  test("parse: empty pre-release identifier") {
    SemVer.parse("5.6.7-") shouldBe None
  }

  test("parse: with build metadata") {
    SemVer.parse("1.0.0+20130313144700") shouldBe
      Some(SemVer(1, 0, 0, None, Some("20130313144700")))
    SemVer.parse("1.0.0-beta+exp.sha.5114f85") shouldBe
      Some(SemVer(1, 0, 0, Some("beta"), Some("exp.sha.5114f85")))
  }

  test("parse: empty build metadata") {
    SemVer.parse("6.7.8+") shouldBe None
    SemVer.parse("9.10.11-M1+") shouldBe None
  }

  test("parse: negative numbers") {
    SemVer.parse("-1.0.0") shouldBe None
    SemVer.parse("0.-1.0") shouldBe None
    SemVer.parse("0.0.-1") shouldBe None
  }

  test("parse: leading zeros") {
    SemVer.parse("01.0.0") shouldBe None
    SemVer.parse("0.01.0") shouldBe None
    SemVer.parse("0.0.01") shouldBe None
  }

  test("getChange") {
    SemVer.getChange(SemVer(1, 3, 4, None, None), SemVer(2, 1, 2, None, None)) shouldBe
      Some(Change.Major)
    SemVer.getChange(SemVer(2, 3, 4, None, None), SemVer(2, 5, 2, None, None)) shouldBe
      Some(Change.Minor)
    SemVer.getChange(
      SemVer(2, 3, 4, Some("SNAP1"), None),
      SemVer(2, 3, 4, Some("SNAP2"), None)
    ) shouldBe
      Some(Change.PreRelease)
    SemVer.getChange(
      SemVer(2, 3, 4, Some("M1"), Some("1")),
      SemVer(2, 3, 4, Some("M1"), Some("2"))
    ) shouldBe
      Some(Change.BuildMetadata)
    SemVer.getChange(
      SemVer(2, 3, 4, Some("M1"), None),
      SemVer(2, 3, 4, Some("M1"), None)
    ) shouldBe None
    SemVer.getChange(SemVer(0, 20, 0, Some("M4"), None), SemVer(0, 20, 3, None, None)) shouldBe
      Some(Change.PreRelease)
  }
} 
Example 27
Source File: SemVer.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.data

import cats.implicits._
import eu.timepit.refined.cats.refTypeEq
import eu.timepit.refined.types.numeric.NonNegBigInt
import eu.timepit.refined.types.string.NonEmptyString
import org.scalasteward.core.data.SemVer.Change._
import org.scalasteward.core.util.string.parseNonNegBigInt

final case class SemVer(
    major: NonNegBigInt,
    minor: NonNegBigInt,
    patch: NonNegBigInt,
    preRelease: Option[NonEmptyString],
    buildMetadata: Option[NonEmptyString]
) {
  def render: String =
    s"$major.$minor.$patch" + preRelease.fold("")("-" + _) + buildMetadata.fold("")("+" + _)
}

object SemVer {
  def parse(s: String): Option[SemVer] = {
    def parseIdentifier(s: String): Option[NonEmptyString] =
      Option(s).map(_.drop(1)).flatMap(NonEmptyString.unapply)

    val pattern = raw"""(\d+)\.(\d+)\.(\d+)(\-[^\+]+)?(\+.+)?""".r
    s match {
      case pattern(majorStr, minorStr, patchStr, preReleaseStr, buildMetadataStr) =>
        for {
          major <- parseNonNegBigInt(majorStr)
          minor <- parseNonNegBigInt(minorStr)
          patch <- parseNonNegBigInt(patchStr)
          preRelease = parseIdentifier(preReleaseStr)
          buildMetadata = parseIdentifier(buildMetadataStr)
          semVer = SemVer(major, minor, patch, preRelease, buildMetadata)
          if semVer.render === s
        } yield semVer
      case _ => None
    }
  }

  sealed abstract class Change(val render: String)
  object Change {
    case object Major extends Change("major")
    case object Minor extends Change("minor")
    case object Patch extends Change("patch")
    case object PreRelease extends Change("pre-release")
    case object BuildMetadata extends Change("build-metadata")
  }

  def getChange(from: SemVer, to: SemVer): Option[Change] =
    if (from.major =!= to.major) Some(Major)
    else if (from.minor =!= to.minor) Some(Minor)
    else if (from.preRelease =!= to.preRelease) Some(PreRelease)
    else if (from.patch =!= to.patch) Some(Patch)
    else if (from.buildMetadata =!= to.buildMetadata) Some(BuildMetadata)
    else None
}