0

I'm writing scalajs facade for pouchdb

code : https://gist.github.com/chandu0101/62013de47bf5ee4d2412

how to define facade for API name changes which emits events and return a cancel method ..

invariant
  • 8,758
  • 9
  • 47
  • 61

1 Answers1

3

Defining Scala.js facade types is all about giving static types to a JavaScript API. Usually the documentation of the JavaScript does mention types, which can therefore be translated into a formal definition pretty easily.

In this case, the changes methods returns an EventEmitter, which is the first thing you need. Let us define this type, and in particular its on method:

class EventEmitter extends js.Object {
  def on(event: String, listener: js.Function): this.type = js.native
  ...
}

We have to be very imprecise for the type of listener, unfortunately, because the actual type will very much depend on the event string, and the particular uses of that emitter. In general, we cannot predict anything at this point.

The documentation of EventEmitter doesn't mention a cancel() method, which is a bit weird since apparently that method can be called on the emitter returned by changes. So we'll define a subtype for the particular emitter returned by changes:

trait ChangesEventEmitter extends EventEmitter {
  def cancel(): Unit = js.native
}

We can also take advantage of this specialized trait to enable a more precise type of listener for particular events. In this case, let us do it for the change event:

object ChangesEventEmitter {
  implicit class ChangesEventEmitterEvents(
      val self: ChangesEventEmitter) extends AnyVal {
    def onChange(listener: js.Function1[js.Dynamic, Any]): self.type =
      self.on("change", listener)
  }
}

Finally, you need a type for the options parameter of the db.changes method. The type itself is usually a trait with many immutable fields:

trait DBChangesOptions extends js.Object {
  val include_docs: js.UndefOr[Boolean] = js.native
  val limit: js.UndefOr[Int] = js.native
  ...
}

To construct an instance of such a type, you may either go with an apply method in the companion object with default arguments (see this SO question), or you can create a Builder-like class for it.

And now, we can finally declare the changes method itself:

def changes(options: DBChangesOptions = ???): ChangesEventEmitter = js.native
Community
  • 1
  • 1
sjrd
  • 21,805
  • 2
  • 61
  • 91
  • thank you very much , regarding options trait and companion objects i am already doing that for other methods you can check in gist :) – invariant Feb 16 '15 at 12:21
  • could you please explain me how companion object ChangesEventEmitter works ... ? – invariant Feb 23 '15 at 01:45
  • 1
    It works just like any other [implicit class](http://docs.scala-lang.org/overviews/core/implicit-classes.html). There's nothing Scala.js-specific in there. – sjrd Feb 23 '15 at 02:25