Skip to content

Commit

Permalink
Enhance react-apollo logics
Browse files Browse the repository at this point in the history
  • Loading branch information
trungfinity committed Dec 2, 2017
1 parent 146d17d commit 69d2590
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 28 deletions.
3 changes: 3 additions & 0 deletions modules/apollo/apollo.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
lazy val `scalajs-fetch` = LocalProject("scalajs-fetch")
lazy val `scalajs-node-fetch` = LocalProject("scalajs-node-fetch")

lazy val `scalajs-noton-generic` = LocalProject("scalajs-noton-generic")

lazy val `scalajs-graphql-tools` = project
.in(file("graphql-tools"))
.settings(
Expand Down Expand Up @@ -83,6 +85,7 @@ lazy val `scalajs-react-apollo` = project
.in(file("react-apollo"))
.dependsOn(
`scalajs-apollo-client`,
`scalajs-noton-generic`,
`scalajs-graphql-tools` % Test,
`scalajs-apollo-link-mock` % Test,
`scalajs-apollo-cache-inmemory` % Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (C) 2017 Anduin Transactions, Inc.

package anduin.scalajs.react.apollo

import scala.scalajs.js

import anduin.scalajs.noton.Decoder
import anduin.scalajs.noton.generic.deriveDecoder

final case class ApolloQueryProps[Data](
data: Option[Data],
loading: Boolean
)(
raw: js.Any
)

object ApolloQueryProps {

implicit def decoder[Data: Decoder]: Decoder[ApolloQueryProps[Data]] = {
deriveDecoder[ApolloQueryProps[Data]]
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (C) 2017 Anduin Transactions, Inc.

package anduin.scalajs.react.apollo

import scala.language.higherKinds
import scala.scalajs.js

import japgolly.scalajs.react.{Children => ChildrenType}
import japgolly.scalajs.react.internal.Box

import anduin.scalajs.noton.{Decoder, Encoder}

// scalastyle:off underscore.import
import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom.html_<^._
// scalastyle:on underscore.import

final class HigherOrderComponent[Props, ChildProps](
raw: internal.HigherOrderComponent[js.Object, js.Object]
)(
implicit encoder: Encoder[Props],
decoder: Decoder[ChildProps]
) {

def apply[Ctor[-p, +u] <: CtorType[p, u], Children <: ChildrenType](
component: ScalaComponent[ChildProps, _, _, Ctor]
)(
implicit childCtor: CtorType.Summoner.Aux[Box[ChildProps], Children, Ctor],
ctor: CtorType.Summoner[js.Object, Children]
): JsComponent.ComponentWithRoot[ // scalastyle:ignore no.whitespace.after.left.bracket
Props,
ctor.CT,
JsComponent.Unmounted[js.Object, Null],
js.Object,
ctor.CT,
JsComponent.Unmounted[js.Object, Null]
] = {
val render = { raw: js.Any =>
decoder(raw) match {
case Right(childProps) =>
val children = PropsChildren
.fromRawProps(raw.asInstanceOf[js.Object]) // scalastyle:ignore token
.toList
.map(VdomNode.apply)
component.ctor.applyGeneric(childProps)(children: _*).raw

case Left(throwable) =>
<.span(throwable.getMessage)
}
}

JsComponent[js.Object, Children, Null](raw(render)).cmapCtorProps { props: Props =>
encoder(props).asInstanceOf[js.Object] // scalastyle:ignore token
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ package anduin.scalajs.react.apollo

import scala.scalajs.js

final case class Query[Data <: js.Object, Vars <: js.Object](
raw: internal.Query[Data, Vars]
)
trait Query {
type Variables
type Data
val raw: internal.Query[js.Object, js.Object]
}

object Query {

type Aux[Variables0, Data0] = Query { // scalastyle:ignore structural.type
type Variables = Variables0
type Data = Data0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@ package anduin.scalajs.react.apollo
import scala.language.higherKinds
import scala.scalajs.js

import anduin.scalajs.react.apollo.internal.{ApolloQueryProps, HigherOrderComponent}
import anduin.scalajs.noton.{Decoder, Encoder}

object ReactApollo {

def graphql[Vars <: js.Object, Data <: js.Object](
query: Query[Vars, Data]
): HigherOrderComponent[Vars, ApolloQueryProps[Data]] = {
internal.ReactApollo.graphql(query.raw)
def graphql[Variables, Data](
query: Query.Aux[Variables, Data]
)(
implicit encoder: Encoder[Variables],
decoder: Decoder[Data]
): HigherOrderComponent[Variables, ApolloQueryProps[Data]] = {
new HigherOrderComponent[Variables, ApolloQueryProps[Data]](
internal.ReactApollo
.graphql(query.raw)
// scalastyle:off token
.asInstanceOf[internal.HigherOrderComponent[js.Object, js.Object]] // scalastyle:on token
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package anduin.scalajs.react.apollo.internal

import scala.scalajs.js

trait ApolloQueryProps[Data] extends js.Object {
trait ApolloQueryProps[Data <: js.Object] extends js.Object {
val data: js.UndefOr[Data]
val loading: Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import scala.scalajs.js.annotation.{JSImport, JSName}
@js.native
object GraphqlTag extends js.Object {

@JSName(JSImport.Default) def gql[Vars <: js.Object, Data <: js.Object](
@JSName(JSImport.Default) def gql[Variables <: js.Any, Data <: js.Any](
queryString: String
): Query[Vars, Data] = js.native
): Query[Variables, Data] = js.native
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import japgolly.scalajs.react.raw.ReactClass
@js.native
trait HigherOrderComponent[Props <: js.Object, ChildProps <: js.Object] extends js.Object {

def apply[Extra <: js.Object](
def apply[Extra <: js.Any](
component: js.Any // Cannot make it more type-safe
): ReactClass[ChildProps with Extra, Null] = js.native
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ package anduin.scalajs.react.apollo.internal
import scala.scalajs.js

@js.native
trait Query[Vars <: js.Object, Data <: js.Object] extends js.Object
trait Query[Variables <: js.Any, Data <: js.Any] extends js.Object
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import japgolly.scalajs.react.raw._
@js.native
object ReactApollo extends js.Object {

def graphql[Vars <: js.Object, Data <: js.Object](
query: Query[Vars, Data]
): HigherOrderComponent[Vars, ApolloQueryProps[Data]] = js.native
def graphql[Variables <: js.Object, Data <: js.Object](
query: Query[Variables, Data]
): HigherOrderComponent[Variables, ApolloQueryProps[Data]] = js.native

def getDataFromTree(component: ReactElement): js.Promise[Undefined] = js.native
def renderToStringWithData(component: ReactElement): js.Promise[String] = js.native
Expand Down

0 comments on commit 69d2590

Please sign in to comment.