Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Mar 09 2020 17:00
    tindzk commented #37
  • Mar 08 2020 01:03
    raquo commented #37
  • Mar 07 2020 21:19
    raquo edited #37
  • Mar 07 2020 21:15
    raquo edited #37
  • Mar 07 2020 21:12
    raquo edited #37
  • Mar 07 2020 21:12
    raquo edited #37
  • Mar 07 2020 21:11
    raquo edited #37
  • Mar 07 2020 21:10
    raquo opened #37
  • Jul 10 2019 07:26

    tindzk on v0.2.1

    (compare)

  • Jul 10 2019 07:26

    tindzk on master

    Build: Publish v0.2.1 Build: Change version to v0.2.2… (compare)

  • Jul 09 2019 14:59

    tindzk on manual

    (compare)

  • Jul 09 2019 14:59

    tindzk on master

    Manual: Add example for encodin… Merge pull request #36 from spa… (compare)

  • Jul 09 2019 14:59
    tindzk closed #36
  • Jul 09 2019 14:59

    tindzk on scala213

    (compare)

  • Jul 09 2019 14:58

    tindzk on master

    Build: Add support for Scala 2.… Merge pull request #35 from spa… (compare)

  • Jul 09 2019 14:58
    tindzk closed #35
  • Jul 09 2019 14:57

    tindzk on parse-opt-elems

    (compare)

  • Jul 09 2019 14:57

    tindzk on master

    Route: Fix parsing of optional … Merge pull request #34 from spa… (compare)

  • Jul 09 2019 14:57
    tindzk closed #34
  • Jul 09 2019 14:57

    tindzk on redundant-amp

    (compare)

Darren Gibson
@zarthross
This message was deleted
@tindzk I like the idea of a generic Router for Scala.js that I can use in various projects (for example in one project I'm using Scala-Tags and Scala.Rx and would love a router), anyway you can add some issues/milestones/something so I can have some clues on how I might be able to contribute?
Tim Nieradzik
@tindzk
Thanks for your interest! If you'd like to help out, I'd love to discuss some design considerations with you.
As per your suggestion I have created a couple of tickets.
Let me know if you have any other ideas.
Darren Gibson
@zarthross
Awesome, I would love to help out.
I read the issue #19 on widok, and certainly agree with most of your concerns.
As for the Akka support, personally, I'm interested in SPA development right now so jvm support isn't a priority for me, but I can see the importance for hybrid SPA applications. I feel though that if akka support is added, it should be added in a separate library so people feel they can easily add support for other frameworks like play or scalatra, finagle without pulling in akka.
On the overall design, I would love to see this router support Reverse Routing similiar to what playframework can do (https://www.playframework.com/documentation/2.4.x/ScalaRouting#Reverse-routing This is not an endorsement of how playframework does its routing, just a feature i would like to see)
Darren Gibson
@zarthross
I feel reverse routing is essential since routes can change. Being able to know at compile time if a route has been broken is extremely useful, which is why I'm a fan of Autowire (https://github.com/lihaoyi/autowire)
Tim Nieradzik
@tindzk
That's a great idea, indeed. We should definitely strive for type-safety when referencing routes.
Tim Nieradzik
@tindzk

Here is how I'm using MetaRouter in one of my projects:

object Routes {
  val Upload = Route("upload")
  val Library = Route("library")
  val Details = Route("details")

  def upload(): Route = Upload
  def library(): Route = Library
  def details(contentId: Long): Route =
    Details.copy(path = Details.path + "/" + contentId)
  ...
}

object MyRouter extends Router {
  override def dispatch(route: Route, attach: Boolean = false): Unit =
    route.path match {
      case Routes.Library.path => ...
      case Routes.Upload.path => ...      
      case x if x.startsWith(Routes.Details.path) => ...
  }
}

To come up with a better DSL we should discuss ideas for:

a) Specifying routes
b) Instantiating routes
c) Matching routes
d) Registering a JavaScript handler

Tim Nieradzik
@tindzk

To get the brainstorming started, I'll toss in an example how I envision the DSL to look like:

val Details : Route[Int] = "details" / Arg[Int]("contentId")
val UserInfo: Route[(String, Boolean)] = "user" / Arg[String]("user") / Arg[Boolean]("details")

val userInfo: InstantiatedRoute[(String, Boolean)] = UserInfo("bob", false)
userInfo == "user" / "bob" / false
userInfo.url == "user/bob/false"

Route.parse("a/b/c") == "a" / "b" / "c"

userInfo.matches(UserInfo) == true

("user" / "bob").errorMessage(UserInfo) == Some("`user` not specified")

val router = new Router(Seq(Details, UserInfo))
val matchingRoutes = Seq[Route[_]] = router.filter(userInfo)
matchingRoutes == Seq(UserInfo)

Please criticise and point out any shortcomings. :)

Darren Gibson
@zarthross
I think this line ("user" / "bob").errorMessage(UserInfo) == Some("`user` not specified") should be ("user" / "bob").errorMessage(UserInfo) == Some("`details` not specified")
perhaps val router = Router(Details, UserInfo) would be cleaner
using an apply method with a varaible parameter list..
But yeah, so far, I like it, could use a little ironing but i think its a good start.
Darren Gibson
@zarthross
Worked on the Route DSL a little this weekend... here is a sample of what it looks like so far:
 "Multiple Routes with the same Arg Types" should "be equal" in {
    val foo = !# / "asdf" / Arg[Int]("foo") / Arg[Boolean]("bar")
    val bar = !# / "asdf" / Arg[Int]("foo") / Arg[Boolean]("bar")

    assert(foo === bar)
  }

  it should "be equal even with different names" in {
    val foo = !# / "asdf" / Arg[Int]("foo") / Arg[Boolean]("bar")
    val bar = !# / "asdf" / Arg[Int]("foo1") / Arg[Boolean]("bar1")

    assert(foo === bar)
  }

  "Multiple Routes with the different Arg Types" should "not be equal" in {
    val foo = !# / "asdf" / Arg[Int]("foo") / Arg[Boolean]("bar")
    val bar = !# / "asdf" / Arg[Boolean]("fdas") / Arg[Int]("asdf")

    assert(foo !== bar)
  }

  it should "not be equal even with the same names" in {
    val foo = !# / "asdf" / Arg[Int]("foo") / Arg[Boolean]("bar")
    val bar = !# / "asdf" / Arg[Boolean]("foo") / Arg[Int]("bar")

    assert(foo !== bar)
  }

The InstantiatedRoute looks something like this:

  "InstantiatedRoute" should "be created by filling a Route's Args" in {
    val UserInfo = !# / Arg[Boolean]("details")

    val ui1 = UserInfo(false)

    val ui2: InstantiatedRoute[_, _] = UserInfo(false)
  }

  it should "be created by filling a Route's Args in a complex example" in {
    val UserInfo =  !# / "user" / Arg[String]("user") / Arg[Boolean]("details")

    val ui1 = UserInfo(false, "bob")

    val ui2: InstantiatedRoute[_ , _] = UserInfo(false, "bob")
  }

Full type signature of InstantiatedRoute were removed for brevity.

Unfortunately the parameters on apply for Route to create an InstantiatedRoute are reversed, but I'm working on a fix for that.
Darren Gibson
@zarthross
@tindzk ^ What do you think of using '!#' for the start of a Route? I was trying to make it clear that it was an absolute URL and not a relative one. FYI I'm using shapeless with HLists, so thats part of the reason the UserInfo.apply's arguments are showing up in reverse for the moment.
Tim Nieradzik
@tindzk

Indeed, the error message should be: details not specified.

I think it's a good idea to provide the apply() method as you suggested.

I am not sure !# is an intuitive operator. How about this:

val foo = Root / "asdf" / Arg[Int]("foo") / Arg[Boolean]("bar")

(or Index?)

Apart from this it looks really good!

We may also consider providing methods, e.g. Akka provides path() and pathPrefix().

@zarthross I have given you writing permissions to the repository. So if you want to push your changes in a new branch, please go ahead!
Darren Gibson
@zarthross
Awesome. I still have some clean up before I'm happy with it. I'll try and get what I have pushed over the weekend.
Darren Gibson
@zarthross
@tindzk Pushed my idea for a Route DSL to https://github.com/zarthross/MetaRouter/tree/new-route-dsl. I haven't spent much time on the Router portion, but I have some thoughts I'll try to put to code this week.
Tim Nieradzik
@tindzk
Thanks! I'll review it over the next few days.
Tim Nieradzik
@tindzk
@zarthross Impressive work! It's a great idea to use Shapeless. I made a few minor changes here.
Darren Gibson
@zarthross
Kool, I'll look at the changes you made later when i get a chance.
Tim Nieradzik
@tindzk
Do you have an idea how we could merge fill and fillN (see also f455b92aff451799f023d4d9379198ff3248ad17)?
Darren Gibson
@zarthross
Just a cursorer look though, I'm concerned about your move of matches, i think it breaks the type safey of the returned value.
Tim Nieradzik
@tindzk
I actually simplified the type to HList
Darren Gibson
@zarthross
that was the mistake
the Arg Parameter is specifically calculated at compile time based ont eh ROUTE type
Tim Nieradzik
@tindzk
But from what I understood it was untyped before as well.
Darren Gibson
@zarthross
it was type A from CanFillRoute
which was infered from FlatMapper.Aux[ConvertArgs.type, D, A]
Tim Nieradzik
@tindzk
Exactly, and A was determined for fill()'s arguments
But as matches only takes a string, it A is just HList
Am I mistaken?
I had to inline CanFillRoute because IntelliJ didn't find those methods
Darren Gibson
@zarthross
The type A parameter is just the T part of the Args[T] in the ROUTE hlist. I'm pull out the T's to make A
so its more than just an HList, its a specific type known at compile time.