Skip to content

Releases: scalamolecule/molecule

v1.1.0 Remove proprietary dependencies

15 Jan 15:51
Choose a tag to compare

Dependencies on proprietary Datomic dev-local and pro systems are now removed from the distributed core molecule module. This allows using Molecule with Datomic free without having to download other free but proprietary Datomic dev-tools and pro database.

Tests in the non-distributed moleculeTests module still depend on dev-local and pro to ensure that all Datomic systems work with Molecule.

The sample projects in the molecule-samples repo show how to use Molecule with any Datomic database system.

Adjustments to molecule RPC interface

27 Dec 15:32
Choose a tag to compare

RPC method args as generic java.nio.ByteBuffer instead of akka.util.ByteString.

Upgrade datomic-client-api-java-scala to 1.0.3

25 Dec 13:36
Choose a tag to compare

Upgrading datomic-client-api-java-scala to 1.0.3 (transient fs2 upgrade to 3.2.3)

Upgrade to Scala.js 1.8, js-dom 2.0

19 Dec 17:51
Choose a tag to compare

Introduces "org.scala-js" %%% "scala-js-macrotask-executor" % "1.0.0" as ExecutionContext in most of the code base.

Molecule 1.0.0

29 Nov 21:31
Choose a tag to compare

This is the first major release of Molecule! Here are some of the major changes compared to earlier iterations:

Asynchronous and non-blocking api

Molecule is now fully asynchronous and non-blocking. Futures with data are returned that we can then map over:

// transactions"Ben").age(42) => ...)

// queries => ...)

// Multiple transactions/queries
for {
  _ <-"Ben").age(42).save
  result <-
} yield result

Scala.js implementation

Molecule is now fully implemented with Scala.js too. This allows us to transact and query data directly from the client/js side without needing to implement shared RPC interfaces on the server side!

Molecule transparently sends and retrieves data via ajax calls to the server and takes care of marshalling data back and forth with highly efficient Byte encoding/decoding using BooPickle.

You can therefore now make transparent RPC calls with molecules from the client exactly as if the call was made from the server side.

Float and Byte types dropped

Due to limitations in JavaScript, some Float precision is lost on the js platform. Since Molecule is intended to be used on the Scala.js platform too, the Float type is therefore not implemented. Please use Double instead to ensure double precision.

Due to certain Datomic limitation of Bytes, Molecule doesn't implement the Byte type neither.

3 output types

Fetched data can now be returned as tuples, objects or json:

val names           : Future[List[String]]                 =
val namesAndAges    : Future[List[(String, Int)]]          =
val namesAgesMembers: Future[List[(String, Int, Boolean)]] =
// etc..
for {
  // Single row/object
  ben <- Person.name_("Ben")
  _ = ben.age ==> 23
  _ = ben.gender ==> "male"
  _ = ben.Address.street ==> "Broadway" // Note Address namespacing
  _ = ==> "New York" // Note Address.City namespacing
  // Multiple rows/objects
  _ <- { person =>
      s"${} is ${person.age} yeas old and lives on " +
        s"${person.Address.street}, ${}"
    // "Ben is 23 years old and lives on Broadway, New York"
} yield ()
for {
  _ <- Ns.str.Ref1.int1 insert List(("a", 1), ("b", 2))

  _ <- ==>
      |  "data": {
      |    "Ns": [
      |      {
      |        "str": "a",
      |        "Ref1": {
      |          "int1": 1
      |        }
      |      },
      |      {
      |        "str": "b",
      |        "Ref1": {
      |          "int1": 2
      |        }
      |      }
      |    ]
      |  }
} yield ()

To save time generating boilerplate code, the generated boilerplate jars for all tests are attached as a binaries. Unpack and place in respective js/jvm/shared folders in the moleculeTests folder.

Time getters for object output

15 Mar 12:39
Choose a tag to compare

All time getters implemented for object output.

Each getter comes in a synchronous and asynchronous version:

// All objects materialized in List
getObjListAsOf(…)       getAsyncObjListAsOf(…)
getObjListSince(…)      getAsyncObjListSince(…)
getObjListWith(…)       getAsyncObjListWith(…)
getObjListHistory(…)    getAsyncObjListHistory(…) // History only for List of objects

// All objects materialized in fast Array
getObjArrayAsOf(…)      getAsyncObjArrayAsOf(…)
getObjArraySince(…)     getAsyncObjArraySince(…)
getObjArrayWith(…)      getAsyncObjArrayWith(…)

// Object creation/casting deferred for each `next` call
getObjIterableAsOf(…)   getAsyncObjIterableAsOf(…)
getObjIterableSince(…)  getAsyncObjIterableSince(…)
getObjIterableWith(…)   getAsyncObjIterableWith(…)

Each getter can have a t (time t or transaction id), java.util.Date or TxReport applied plus optionally a limit on output. A List of objects as of some point in time can for instance be retrieved with the following getter signatures:

getObjListAsOf(t: Long) // t or tx
getObjListAsOf(tx: TxReport)
getObjListAsOf(date: java.util.Date)

getObjListAsOf(t: Long, limit: Int)
getObjListAsOf(tx: TxReport, limit: Int)
getObjListAsOf(date: java.util.Date, limit: Int)

Molecule object output and dynamic molecules

04 Mar 14:31
Choose a tag to compare

Return each data row as an object with named properties.

As an alternative to tuple output, object properties make it easy to map molecules to forms and other larger structures that benefit from being able to navigate many attributes/properties by name rather than tuple arity position (_1, _2 etc). Property names and types are inferred by the IDE even for references to related data that can nest up to 7 levels deep.

val ben = Person.name_("Ben")

ben.age === 23
ben.gender === "male"
ben.Address.street === "Broadway" === "New York"

Fetch multiple objects with getObjList: { person =>
  println(s"${} is ${person.age} yeas old and lives on ${person.Address.street}, ${}")

Dynamic molecules

An exotic new feature that could help domain modelling is the ability to add a code body to a molecule! A Molecule macro makes data of a single molecule object available to a locally defined body of code. And Scala's Dynamic feature makes the code dynamically available from the outside:

val ben = m("Ben") { self =>
  def info = s"${} (${self.age}, ${self.gender}) lives on ${self.Address.street}, ${}" 

// We can now both access data and call body code
ben.age === 23
ben.gender === "male"
ben.Address.street === "Broadway" === "New York" === "Ben (23, male) lives on Broadway, New York"

Dynamic molecules offer combined data and functionality as an alternative to populating more rigid external domain case classes.

Json output dropped

16 Jan 22:04
Choose a tag to compare

Json as output is dropped which means that methods getJson and getAsyncJson are no longer available on molecules.

The semantics were unclear and json can anyway easily be made with any desired semantics from Model and typed tuples instead. Json output also felt like a black sheep in the typed Molecule eco-system. Moving forward now with what Molecule does best: outputting typed and molecule-matching data.

Targeting Datomic Peer + Peer-Server + Cloud

03 Jan 21:21
Choose a tag to compare

Major upgrade making Molecule fully compliant with all three Datomic database systems:

  • Peer (On-Prem, Java API)
  • Peer Server (Clojure Client API)
  • Cloud / Dev-Local (Clojure Client API)

All 1400+ tests pass with all three systems. See test spec on how to set up each system.

Upgrade to ScalaJS 1.3

31 Oct 13:46
Choose a tag to compare

Upgrading to sbt 1.4.1 too.