All Downloads are FREE. Search and download functionalities are using the official Maven repository.

grist.Document.scala Maven / Gradle / Ivy

The newest version!
package grist

import cats.data.Validated
import cats.implicits.{toFunctorFilterOps, toShow}
import io.circe.*
import io.circe.syntax.EncoderOps
import zio.http.MediaType
import zio.stream.UStream
import zio.{Task, ZIO}

//noinspection ScalaUnusedSymbol
class Document(gristClient: GristClient, docId: String) extends DocumentBase {
  private def docApi = gristClient.docs(docId)

  case class Table[A: Decoder: Encoder](tableName: String) extends TableBase[A] {
    private def tableApi = docApi.tables(tableName)

    override def getRecords(filter: Map[String, Set[Json]] = Map.empty): Task[List[Record[A]]] =
      for {
        records <- tableApi.records.list(filter)
        res     <- ZIO.foreach(records.records) { case Models.Record(id, fields) =>
                     val json = fields.asJson
                     Decoder[A].decodeAccumulating(HCursor.fromJson(json)) match {
                       case Validated.Valid(a)          => ZIO.some(Record(id, a))
                       case Validated.Invalid(failures) =>
                         ZIO.foreachDiscard(failures.toList) { e =>
                           ZIO.logError(s"${e.show}, original JSON: ${json.spaces2}")
                         } *>
                           ZIO.none
                     }
                   }
      } yield res.flattenOption

    override def getRecordsById(ids: Set[Reference[A]]): Task[List[Record[A]]] =
      if (ids.isEmpty)
        ZIO.succeed(Nil)
      else
        getRecords(filter = Map("id" -> ids.map(_.asJson)))

    override def getRecordById(id: Reference[A]): Task[A] =
      getRecordsById(Set(id))
        .flatMap(response => ZIO.getOrFail(response.lastOption).map(_.fields))

    override def addRecords(records: Seq[A]): Task[List[Reference[A]]] =
      for {
        ids <- tableApi.records.add(Models.RecordsWithoutId(records.toList.map { a =>
                 Models.RecordWithoutId(a.asJson.asObject.map(_.toMap).getOrElse(Map.empty))
               }))
      } yield ids.records.map { case Models.RecordWithoutFields(id) =>
        Reference[A](id)
      }

    override def addRecordRaw(record: Map[String, Json]): Task[Int] =
      for {
        results <- tableApi.records.add(Models.RecordsWithoutId(List(Models.RecordWithoutId(record))))
        result  <- ZIO.getOrFail(results.records.headOption)
      } yield result.id

    override def deleteRecords(ids: Set[Reference[A]]): Task[Unit] =
      for {
        _ <- tableApi.data.delete(ids.map(_.id))
      } yield ()
  }

  def uploadAttachment(data: UStream[Byte], mediaType: MediaType, filename: Option[String] = None) =
    docApi.attachments.upload(GristClient.AttachmentInfo(data, mediaType, filename))
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy