scalajs-io/nodejs

This project provides Scala.js type-safe bindings for Node.js (current) v8.7.0 and LTS v6.11.4 APIs. The platform supports MEAN (MongoDB, Express, AngularJs, NodeJS), Cassandra, MySQL and many other npm projects.

Scala

163

204 commits

updated May 20, 2023

See the code

README

NodeJS (current & LTS)

This is a complete Scala.js facade for Node.js and npm packages; which means you can develop full-blown Node.js applications using popular JavaScript software stacks including the MEAN Stack (MongoDB, Express, Angular, Node), Cassandra, MySQL and many other popular npm packages.

Table of Contents

Introduction

The goal of this project is to provide a complete Scala.js binding for the entire MEAN Stack. Why? Because I love NodeJS, but I have a love/hate relationship with JavaScript. And many others feel the same way about JavaScript, which is why there are so many languages that are designed to improve the experience (CoffeeScript, TypeScript, Scala.js and others). Simply put, ScalaJs.io let's me have my cake and eat it too! And as such, I've gone to great lengths to bring all the things you love about developing applications on the MEAN Stack to Scala.

ScalaJs.io is a componentized platform; allowing developers to use only the features they want. If all your application requires is a binding for AngularJS, you can use just that. Alternatively, you could use only the Node bindings, or the entire MEAN stack (or any of the bundled npm library bindings).

Currently, there are at least four development use cases for ScalaJs.io:

  • Building full MEAN stack applications using the bundled MongoDB, Express, Angular and Node bindings.
  • Building rich thin-client web front-ends using AngularJS bindings only (with any backend).
  • Building REST services using Node (and optionally Express) bindings only.
  • Building CLI applications using Node bindings only.

Development

Build Requirements

Build/publish the SDK

 $ sbt clean publish-local

Resolvers

To add the ScalaJs.io bindings/library to your project, add the following to your build.sbt:

resolvers += Resolver.sonatypeRepo("releases") 

Developed using ScalaJs.io

The following applications were developed using ScalaJs.io:

ApplicationFrontendBackendScalajs.io versionDescription
Phaser-InvadersScala.js + DOMScala + NodeJS0.3.xPort of Phaser Invaders.
SocializeScala.js + AngularJSScala.js + NodeJS0.4.0A Facebook-inspired Social networking web application.
Todo MVCScala.js + AngularJSScala.js + NodeJS0.2.xA simple Todo example application.
TrifectaScala.js + AngularJSScala + Play 2.4.x0.4.0Trifecta is a web-based and CLI tool that simplifies inspecting Kafka messages and Zookeeper data.

The MEAN Stack — AngularJS, MongoDB, Mongoose, Express and more

Module / PackageVersionDescription
angular1.6.3AngularJS/core binding for Scala.js
angular-anchor-scroll1.6.3AngularJS/anchorScroll binding for Scala.js
angular-animate1.6.3AngularJS/animate binding for Scala.js
angular-cookies1.6.3AngularJS/cookies binding for Scala.js
angular-facebook1.6.3AngularJS/facebook binding for Scala.js
angular-md51.6.3AngularJS/md5 binding for Scala.js
angular-file-upload1.6.3AngularJS/fileupload binding for Scala.js
angular-nvd31.6.3AngularJS/nvd3 binding for Scala.js
angular-sanitize1.6.3AngularJS/sanitize binding for Scala.js
angular-ui-bootstrap1.6.3AngularJS/ui-bootstrap binding for Scala.js
angular-ui-router1.6.3AngularJS/ui-router binding for Scala.js
angularjs-toaster1.6.3AngularJS/toaster binding for Scala.js
express4.13.4Fast, unopinionated, minimalist web framework for Node.js
mongodb2.2.22The official MongoDB driver for Node.js.
mongoose4.8.1Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
mpromise0.5.5A promises/A+ conformant implementation, written for mongoose.

Looking for a complete list of available bindings? Go here

Discussions

There's a discussion about ScalaJs.io on Reddit.

Advantages over JavaScript

Scala.js offers many advantages over native JavaScript:

Consider the following example in JavaScript. Here we have a nested collection of callbacks (read: pyramid of doom) in order to gather the information that we display at the end.

JavaScript and Node.js
var output1 = null;
var output2 = null;
var output3 = null;

fs.mkdirp("/a/test/dir", function (err1) {
    Assert.ifError(err1);

    fs.writeFile("/a/test/dir/file.txt", "Hello World", function (err2) {
        Assert.ifError(err2);

        fs.readFile("/a/test/dir/file.txt", function (err3, data) {
            Assert.ifError(err3);
            output1 = data; // ~> Buffer("Hello World")

            fs.unlink("/a/test/dir/file.txt", function (err4) {
                Assert.ifError(err4);

                fs.readdir("/a/test", function (err5, dir) {
                    Assert.ifError(err5);
                    output2 = dir; // ~> ["dir"]

                    fs.stat("/a/test/dir", function (err6, stats) {
                        Assert.ifError(err6);
                        output3 = stats.isDirectory(); // ~> true

                        fs.rmdir("/a/test/dir", function (err7) {
                            Assert.ifError(err7);
                            fs.mkdirp("C:\\use\\windows\\style\\paths", function (err8) {
                                Assert.ifError(err8);
                                
                                console.log("output1 =", output1.toString(), output1);
                                console.log("output2 =", output2);
                                console.log("output3 =", output3)
                            })
                        })
                    })
                })
            })
        })
    })
});

Now consider the equivalent logic in Scala.js using its much more elegant for comprehension:

Scala.js and Node.js
import io.scalajs.nodejs.console
import io.scalajs.nodejs.Fs._
  
for {
  _ <- Fs.mkdirpFuture("/a/test/dir")
  _ <- Fs.writeFileFuture("/a/test/dir/file.txt", "Hello World")
  output1 <- Fs.readFileFuture("/a/test/dir/file.txt") // ~> Buffer("Hello World")
  _ <- Fs.unlinkFuture("/a/test/dir/file.txt")
  output2 <- Fs.readdirFuture("/a/test") // ~> ["dir"]
  output3 <- Fs.statFuture("/a/test/dir").map(_.isDirectory()) // ~> true
  _ <- Fs.rmdirFuture("/a/test/dir")
  _ <- Fs.mkdirpFuture("C:\\use\\windows\\style\\paths")
} {
  console.log("output1 =", output1.toString(), output1)
  console.log("output2 =", output2)
  console.log("output3 =", output3)
}

Node.js

The Node.js integration is nearly complete (feature for feature), and should be more than sufficient for most web-based and CLI applications. Additionally, there are a growing number of third-party (mostly OSS) modules that have been implemented as well, including bcrypt, cassandra-driver, kafka-node, mysql, xml2js and many others.

#### Modules

The following core Node.js modules (v8.7.0) have been implemented:

Node ModuleDescription
assertProvides a simple set of assertion tests that can be used to test invariants.
bufferThe Buffer class was introduced as part of the Node.js API to make it possible to interact with octet streams in the context of things like TCP streams and file system operations.
child_processThe child_process module provides the ability to spawn child processes.
clusterThe cluster module allows you to easily create child processes that all share server ports.
cryptoThe crypto module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign and verify functions.
dnsSupport for DNS queries.
eventsNode.js Events Interface
fsFile I/O is provided by simple wrappers around standard POSIX functions.
httpNode.js HTTP Interface
httpsNode.js HTTPS Interface
netThe net module provides you with an asynchronous network wrapper.
osProvides a few basic operating-system related utility functions.
pathThis module contains utilities for handling and transforming file paths.
querystringThe querystring module provides utilities for parsing and formatting URL query strings.
readlineReadline allows reading of a stream on a line-by-line basis.
replThe REPL provides a way to interactively run JavaScript and see the results.
streamA stream is an abstract interface implemented by various objects in Node.js.
string-decoderThe string_decoder module provides an API for decoding Buffer objects into strings in a manner that preserves encoded multi-byte UTF-8 and UTF-16 characters.
timersThe timer module exposes a global API for scheduling functions to be called at some future period of time.
ttyThe tty module provides the tty.ReadStream and tty.WriteStream classes.
urlThe url module provides utilities for URL resolution and parsing.
utilThe util module is primarily designed to support the needs of Node.js's internal APIs.
vmThe vm module provides APIs for compiling and running code within V8 Virtual Machine contexts.
zlibThis provides bindings to Gzip/Gunzip, Deflate/Inflate, and DeflateRaw/InflateRaw classes.

NOTE: The SBT artifacts for Node.js platform are (choose one):

  • NodeJS v8.7.0: "io.scalajs" %%% "nodejs" % "0.5.0"
  • NodeJS LTS v6.11.4: "io.scalajs" %%% "nodejs-lts" % "0.5.0"
#### Third-party Modules

The following Third Party/OSS Node.js (npm) modules have been implemented:

Module / PackageVersionDescription
async2.0.0Higher-order functions and common patterns for asynchronous code.
bcrypt0.0.3A native JS bcrypt library for NodeJS.
bignum0.12.5Arbitrary-precision integer arithmetic using OpenSSL.
body-parser1.15.1Body parsing middleware.
brake1.0.1Throttle a stream with backpressure.
buffermaker1.2.0buffermaker is a convenient way of creating binary strings.
cassandra-driver3.0.2DataStax Node.js Driver for Apache Cassandra
cheerio0.22.0Tiny, fast, and elegant implementation of core jQuery designed specifically for the server
chalk1.1.3Terminal string styling done right. Much color.
cookie0.3.1HTTP server cookie parsing and serialization
cookie-parser1.4.3Cookie parsing with signatures
colors1.1.2Get colors in your node.js console.
csv-parse1.1.2CSV parsing implementing the Node.js 'stream.Transform' API.
csvtojson1.1.4A tool concentrating on converting csv data to JSON with customised parser supporting.
drama0.1.3drama is an Actor model implementation for JavaScript and Node.js
escape-html1.0.3Escape string for use in HTML
express4.13.4Fast, unopinionated, minimalist web framework for Node.js
express-csv0.6.0express-csv provides response csv easily to express.
express-fileupload0.0.5Simple express file upload middleware that wraps around connect-busboy
express-ws2.0.0WebSocket endpoints for Express applications
feedparser-promised1.1.1Wrapper around feedparser with promises.
filed0.1.0Simplified file library.
github-api-node0.11.2A higher-level wrapper around the Github API.
glob7.1.1A little globber.
html-to-json0.6.0Parses HTML strings into objects using flexible, composable filters.
htmlparser23.9.1A forgiving HTML/XML/RSS parser. The parser can handle streams and provides a callback interface.
jsdom9.9.1A JavaScript implementation of the WHATWG DOM and HTML standards, for use with Node.js
jwt-simple0.5.0JWT(JSON Web Token) encode and decode module
kafka-node0.0.11A node binding for librdkafka
kafka-rest0.0.4REST Proxy wrapper library for Kafka
md52.1.0A JavaScript function for hashing messages with MD5.
memory-fs0.3.0A simple in-memory filesystem. Holds data in a javascript object.
mkdirp0.5.1Recursively mkdir, like mkdir -p.
moment2.17.1Parse, validate, manipulate, and display dates in JavaScript.
moment-timezone0.5.11Parse and display dates in any timezone.
mongodb2.2.22The official MongoDB driver for Node.js.
mongoose4.8.1Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
mpromise0.5.5A promises/A+ conformant implementation, written for mongoose.
multer1.1.0Multer is a node.js middleware for handling multipart/form-data.
mysql2.10.2A node.js driver for mysql.
node-zookeeper-client0.2.2A higher-level ZooKeeper client based on node-zookeeper with support for locking and master election.
numeral2.0.4A javascript library for formatting and manipulating numbers.
oppressor0.0.1Streaming http compression response negotiator.
readable-stream2.2.2Streams3, a user-land copy of the stream library from Node.js.
request2.72.1Simplified HTTP request client.
rxjs4.1.0The Reactive Extensions for JavaScript.
socket.io1.7.2Realtime application framework (Node.JS server).
socket.io-client1.7.2Socket.io client.
splitargs0.0.7Splits strings into tokens by given separator except treating quoted part as a single token.
tingodb0.5.1Embedded Node.js database upward compatible with MongoDB.
tough-cookie2.3.2RFC6265 Cookies and Cookie Jar for node.js.
transducers-js0.4.174A high performance Transducers implementation for JavaScript.
type-is1.6.14Infer the content-type of a request.
watch0.18.0Utilities for watching file trees.
winston2.3.1A multi-transport async logging library for Node.js.
winston-daily-rotate-file1.4.4A multi-transport async logging library for Node.js.
xml2js0.4.16Simple XML to JavaScript object converter.

NOTE: The full SBT artifact expression is: "io.scalajs.npm" %%% "xxxx" % version (e.g. "io.scalajs.npm" %%% "express" % "0.5.0")

I've provided an example to demonstrate how similar the Scala.js code is to the JavaScript that it replaces.

The following is a simple Hello World app in Node using JavaScript:

var http = require("http");
http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
}).listen(8888);

Here's the same example using Scala.js:

import io.scalajs.nodejs.http._
import scalajs.js

Http.createServer((request: ClientRequest, response: ServerResponse) => {
    response.writeHead(200, js.Dictionary("Content-Type" -> "text/plain"))
    response.write("Hello World")
    response.end()
}).listen(8888)

Express.js

The following is a simple Hello World app in Node and Express using JavaScript:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
   res.send('Hello World');
})

var server = app.listen(8081, function () {
  var host = server.address().address
  var port = server.address().port
  console.log("Example app listening at http://%s:%s", host, port)
})

Here's the same example using Scala.js:

import io.scalajs.nodejs.console
import io.scalajs.npm.express._

val app = Express()

app.get("/", (req: Request, res: Response) => res.send("Hello World"))

val server = app.listen(8081, connect)

private def connect: js.Function = () => {
    val host = server.address().address
    val port = server.address().port
    console.log("Example app listening at http://%s:%s", host, port)
}

The following is a more elaborate example:

import io.scalajs.npm.express._
import io.scalajs.util.ScalaJsHelpers._
import scalajs.js

val todos: js.Array[Todo] = emptyArray

val app = Express()

app.use(BodyParser.json())
app.use(BodyParser.urlencoded(new UrlEncodedBodyOptions(extended = true)))   
 
app.get("/api/todo/:id", (request: Request, response: Response) => getTodo(request, response))
app.get("/api/todos", (request: Request, response: Response) => getTodos(request, response))
app.post("/api/todo", (request: Request, response: Response) => createTodo(request, response))

def createTodo(request: Request, response: Response) = {
    request.bodyAs[Todo] match {
        case todo if todo.hasTitle =>
            todo.id = UUID.randomUUID().toString
            todos.push(todo)
            response.send(todos)
        case todo =>
            response.badRequest(todo)
    }
}
  
def getTodo(request: Request, response: Response) = {
    val todoId = request.params("id")
    todos.indexWhereOpt(_.id == todoId) match {
        case Some(index) => response.send(todos(index))
        case None => response.notFound(todoId)
    }
}

def getTodos(request: Request, response: Response) = response.send(todos)

@js.native
trait Todo extends js.Object {
    var id: String = js.native
    var title: String = js.native
    var completed: Boolean = js.native
}

implicit class TodoExtensions(val todo: Todo) extends AnyVal {

    @inline
    def hasId: Boolean = Option(todo).flatMap(t => Option(t.id)).exists(_.trim.nonEmpty)
    
    @inline
    def hasTitle: Boolean = Option(todo).flatMap(t => Option(t.title)).exists(_.trim.nonEmpty)
    
    @inline
    def isComplete: Boolean = hasId && hasTitle

}

MongoDB

The following example demonstrates establishing a connection to MongoDB using Scala.js:

import io.scalajs.nodejs.console
import io.scalajs.npm.mongodb._
import io.scalajs.util.ScalaJsHelper._

// Connection URL. This is where your mongodb server is running.
val url = "mongodb://localhost:27017/test"

// Use connect method to connect to the Server
MongoClient.connect(url, (err, db) => {
    if (isDefined(err)) {
        console.log("Unable to connect to the mongoDB server. Error:", err)
    } else {
        // HURRAY!! We are connected. :)
        console.log("Connection established to: %s", url)
        
        // TODO do some work here with the database.
        
        // close connection
        db.close()
    }
})

Or, if you'd like to be more Scala idiomatic, the connection fragment could be written as follows:

import io.scalajs.nodejs.console
import io.scalajs.npm.mongodb._
import scala.util.{Success, Failure}

MongoClient.connectFuture(url) onComplete {
    case Success(db) =>
        // HURRAY!! We are connected. :)
        console.log("Connection established to: %s", url)

        // TODO do some work here with the database.

        // close connection
        db.close()
    case Failure(e) =>
        console.log("Unable to connect to the mongoDB server. Error:", e.getMessage)  
}

Alternatively, you could choose to use "foreach" to directly manage only the success case:

import io.scalajs.npm.mongodb._
import io.scalajs.util.PromiseHelper._

MongoClient.connectFuture(url) foreach { db => 
    // HURRAY!! We are connected. :)
    console.log("Connection established to: %s", url)

    // TODO do some work here with the database.

    // close connection
    db.close()
}

ScalaJs.io exposes Future-based alternatives to most of the asynchronous functions found in MongoDB, Express, Angular and Node. This means that you can use Scala's amazing for comprehensions to replace the dreaded pyramid of doom callbacks normally associated with JavaScript asynchronous code.

Consider the following:

for {
    // List all the virtual machine images you can use.
    vmImages <- computeManagementClient.virtualMachineVMImages.listFuture
    
    // Create a cloud service.
    computeManagementClient <- computeManagementClient.hostedServices.createFuture(
      HostedServicesOptions(serviceName = serviceName, label = "cloud service 01", location = "West US"))
    
    // Create a virtual machine in the cloud service
    deployment <- computeManagementClient.virtualMachines.createDeploymentFuture(serviceName, deploymentOptions)
} {
    console.info(deployment)
}
angular
mean-stack
mongodb
mongoose
node
nodejs
npm
scala
scala-bindings
scalajs

Contributors

ldaniels528

200 commits

rmmeans

3 commits

ScalaWilliam

1 commits

scalajs-io/nodejs

This project provides Scala.js type-safe bindings for Node.js (current) v8.7.0 and LTS v6.11.4 APIs. The platform supports MEAN (MongoDB, Express, AngularJs, NodeJS), Cassandra, MySQL and many other npm projects.

Scala

163

204 commits

updated May 20, 2023

See the code

README

NodeJS (current & LTS)

This is a complete Scala.js facade for Node.js and npm packages; which means you can develop full-blown Node.js applications using popular JavaScript software stacks including the MEAN Stack (MongoDB, Express, Angular, Node), Cassandra, MySQL and many other popular npm packages.

Table of Contents

Introduction

The goal of this project is to provide a complete Scala.js binding for the entire MEAN Stack. Why? Because I love NodeJS, but I have a love/hate relationship with JavaScript. And many others feel the same way about JavaScript, which is why there are so many languages that are designed to improve the experience (CoffeeScript, TypeScript, Scala.js and others). Simply put, ScalaJs.io let's me have my cake and eat it too! And as such, I've gone to great lengths to bring all the things you love about developing applications on the MEAN Stack to Scala.

ScalaJs.io is a componentized platform; allowing developers to use only the features they want. If all your application requires is a binding for AngularJS, you can use just that. Alternatively, you could use only the Node bindings, or the entire MEAN stack (or any of the bundled npm library bindings).

Currently, there are at least four development use cases for ScalaJs.io:

  • Building full MEAN stack applications using the bundled MongoDB, Express, Angular and Node bindings.
  • Building rich thin-client web front-ends using AngularJS bindings only (with any backend).
  • Building REST services using Node (and optionally Express) bindings only.
  • Building CLI applications using Node bindings only.

Development

Build Requirements

Build/publish the SDK

 $ sbt clean publish-local

Resolvers

To add the ScalaJs.io bindings/library to your project, add the following to your build.sbt:

resolvers += Resolver.sonatypeRepo("releases") 

Developed using ScalaJs.io

The following applications were developed using ScalaJs.io:

ApplicationFrontendBackendScalajs.io versionDescription
Phaser-InvadersScala.js + DOMScala + NodeJS0.3.xPort of Phaser Invaders.
SocializeScala.js + AngularJSScala.js + NodeJS0.4.0A Facebook-inspired Social networking web application.
Todo MVCScala.js + AngularJSScala.js + NodeJS0.2.xA simple Todo example application.
TrifectaScala.js + AngularJSScala + Play 2.4.x0.4.0Trifecta is a web-based and CLI tool that simplifies inspecting Kafka messages and Zookeeper data.

The MEAN Stack — AngularJS, MongoDB, Mongoose, Express and more

Module / PackageVersionDescription
angular1.6.3AngularJS/core binding for Scala.js
angular-anchor-scroll1.6.3AngularJS/anchorScroll binding for Scala.js
angular-animate1.6.3AngularJS/animate binding for Scala.js
angular-cookies1.6.3AngularJS/cookies binding for Scala.js
angular-facebook1.6.3AngularJS/facebook binding for Scala.js
angular-md51.6.3AngularJS/md5 binding for Scala.js
angular-file-upload1.6.3AngularJS/fileupload binding for Scala.js
angular-nvd31.6.3AngularJS/nvd3 binding for Scala.js
angular-sanitize1.6.3AngularJS/sanitize binding for Scala.js
angular-ui-bootstrap1.6.3AngularJS/ui-bootstrap binding for Scala.js
angular-ui-router1.6.3AngularJS/ui-router binding for Scala.js
angularjs-toaster1.6.3AngularJS/toaster binding for Scala.js
express4.13.4Fast, unopinionated, minimalist web framework for Node.js
mongodb2.2.22The official MongoDB driver for Node.js.
mongoose4.8.1Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
mpromise0.5.5A promises/A+ conformant implementation, written for mongoose.

Looking for a complete list of available bindings? Go here

Discussions

There's a discussion about ScalaJs.io on Reddit.

Advantages over JavaScript

Scala.js offers many advantages over native JavaScript:

Consider the following example in JavaScript. Here we have a nested collection of callbacks (read: pyramid of doom) in order to gather the information that we display at the end.

JavaScript and Node.js
var output1 = null;
var output2 = null;
var output3 = null;

fs.mkdirp("/a/test/dir", function (err1) {
    Assert.ifError(err1);

    fs.writeFile("/a/test/dir/file.txt", "Hello World", function (err2) {
        Assert.ifError(err2);

        fs.readFile("/a/test/dir/file.txt", function (err3, data) {
            Assert.ifError(err3);
            output1 = data; // ~> Buffer("Hello World")

            fs.unlink("/a/test/dir/file.txt", function (err4) {
                Assert.ifError(err4);

                fs.readdir("/a/test", function (err5, dir) {
                    Assert.ifError(err5);
                    output2 = dir; // ~> ["dir"]

                    fs.stat("/a/test/dir", function (err6, stats) {
                        Assert.ifError(err6);
                        output3 = stats.isDirectory(); // ~> true

                        fs.rmdir("/a/test/dir", function (err7) {
                            Assert.ifError(err7);
                            fs.mkdirp("C:\\use\\windows\\style\\paths", function (err8) {
                                Assert.ifError(err8);
                                
                                console.log("output1 =", output1.toString(), output1);
                                console.log("output2 =", output2);
                                console.log("output3 =", output3)
                            })
                        })
                    })
                })
            })
        })
    })
});

Now consider the equivalent logic in Scala.js using its much more elegant for comprehension:

Scala.js and Node.js
import io.scalajs.nodejs.console
import io.scalajs.nodejs.Fs._
  
for {
  _ <- Fs.mkdirpFuture("/a/test/dir")
  _ <- Fs.writeFileFuture("/a/test/dir/file.txt", "Hello World")
  output1 <- Fs.readFileFuture("/a/test/dir/file.txt") // ~> Buffer("Hello World")
  _ <- Fs.unlinkFuture("/a/test/dir/file.txt")
  output2 <- Fs.readdirFuture("/a/test") // ~> ["dir"]
  output3 <- Fs.statFuture("/a/test/dir").map(_.isDirectory()) // ~> true
  _ <- Fs.rmdirFuture("/a/test/dir")
  _ <- Fs.mkdirpFuture("C:\\use\\windows\\style\\paths")
} {
  console.log("output1 =", output1.toString(), output1)
  console.log("output2 =", output2)
  console.log("output3 =", output3)
}

Node.js

The Node.js integration is nearly complete (feature for feature), and should be more than sufficient for most web-based and CLI applications. Additionally, there are a growing number of third-party (mostly OSS) modules that have been implemented as well, including bcrypt, cassandra-driver, kafka-node, mysql, xml2js and many others.

#### Modules

The following core Node.js modules (v8.7.0) have been implemented:

Node ModuleDescription
assertProvides a simple set of assertion tests that can be used to test invariants.
bufferThe Buffer class was introduced as part of the Node.js API to make it possible to interact with octet streams in the context of things like TCP streams and file system operations.
child_processThe child_process module provides the ability to spawn child processes.
clusterThe cluster module allows you to easily create child processes that all share server ports.
cryptoThe crypto module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign and verify functions.
dnsSupport for DNS queries.
eventsNode.js Events Interface
fsFile I/O is provided by simple wrappers around standard POSIX functions.
httpNode.js HTTP Interface
httpsNode.js HTTPS Interface
netThe net module provides you with an asynchronous network wrapper.
osProvides a few basic operating-system related utility functions.
pathThis module contains utilities for handling and transforming file paths.
querystringThe querystring module provides utilities for parsing and formatting URL query strings.
readlineReadline allows reading of a stream on a line-by-line basis.
replThe REPL provides a way to interactively run JavaScript and see the results.
streamA stream is an abstract interface implemented by various objects in Node.js.
string-decoderThe string_decoder module provides an API for decoding Buffer objects into strings in a manner that preserves encoded multi-byte UTF-8 and UTF-16 characters.
timersThe timer module exposes a global API for scheduling functions to be called at some future period of time.
ttyThe tty module provides the tty.ReadStream and tty.WriteStream classes.
urlThe url module provides utilities for URL resolution and parsing.
utilThe util module is primarily designed to support the needs of Node.js's internal APIs.
vmThe vm module provides APIs for compiling and running code within V8 Virtual Machine contexts.
zlibThis provides bindings to Gzip/Gunzip, Deflate/Inflate, and DeflateRaw/InflateRaw classes.

NOTE: The SBT artifacts for Node.js platform are (choose one):

  • NodeJS v8.7.0: "io.scalajs" %%% "nodejs" % "0.5.0"
  • NodeJS LTS v6.11.4: "io.scalajs" %%% "nodejs-lts" % "0.5.0"
#### Third-party Modules

The following Third Party/OSS Node.js (npm) modules have been implemented:

Module / PackageVersionDescription
async2.0.0Higher-order functions and common patterns for asynchronous code.
bcrypt0.0.3A native JS bcrypt library for NodeJS.
bignum0.12.5Arbitrary-precision integer arithmetic using OpenSSL.
body-parser1.15.1Body parsing middleware.
brake1.0.1Throttle a stream with backpressure.
buffermaker1.2.0buffermaker is a convenient way of creating binary strings.
cassandra-driver3.0.2DataStax Node.js Driver for Apache Cassandra
cheerio0.22.0Tiny, fast, and elegant implementation of core jQuery designed specifically for the server
chalk1.1.3Terminal string styling done right. Much color.
cookie0.3.1HTTP server cookie parsing and serialization
cookie-parser1.4.3Cookie parsing with signatures
colors1.1.2Get colors in your node.js console.
csv-parse1.1.2CSV parsing implementing the Node.js 'stream.Transform' API.
csvtojson1.1.4A tool concentrating on converting csv data to JSON with customised parser supporting.
drama0.1.3drama is an Actor model implementation for JavaScript and Node.js
escape-html1.0.3Escape string for use in HTML
express4.13.4Fast, unopinionated, minimalist web framework for Node.js
express-csv0.6.0express-csv provides response csv easily to express.
express-fileupload0.0.5Simple express file upload middleware that wraps around connect-busboy
express-ws2.0.0WebSocket endpoints for Express applications
feedparser-promised1.1.1Wrapper around feedparser with promises.
filed0.1.0Simplified file library.
github-api-node0.11.2A higher-level wrapper around the Github API.
glob7.1.1A little globber.
html-to-json0.6.0Parses HTML strings into objects using flexible, composable filters.
htmlparser23.9.1A forgiving HTML/XML/RSS parser. The parser can handle streams and provides a callback interface.
jsdom9.9.1A JavaScript implementation of the WHATWG DOM and HTML standards, for use with Node.js
jwt-simple0.5.0JWT(JSON Web Token) encode and decode module
kafka-node0.0.11A node binding for librdkafka
kafka-rest0.0.4REST Proxy wrapper library for Kafka
md52.1.0A JavaScript function for hashing messages with MD5.
memory-fs0.3.0A simple in-memory filesystem. Holds data in a javascript object.
mkdirp0.5.1Recursively mkdir, like mkdir -p.
moment2.17.1Parse, validate, manipulate, and display dates in JavaScript.
moment-timezone0.5.11Parse and display dates in any timezone.
mongodb2.2.22The official MongoDB driver for Node.js.
mongoose4.8.1Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
mpromise0.5.5A promises/A+ conformant implementation, written for mongoose.
multer1.1.0Multer is a node.js middleware for handling multipart/form-data.
mysql2.10.2A node.js driver for mysql.
node-zookeeper-client0.2.2A higher-level ZooKeeper client based on node-zookeeper with support for locking and master election.
numeral2.0.4A javascript library for formatting and manipulating numbers.
oppressor0.0.1Streaming http compression response negotiator.
readable-stream2.2.2Streams3, a user-land copy of the stream library from Node.js.
request2.72.1Simplified HTTP request client.
rxjs4.1.0The Reactive Extensions for JavaScript.
socket.io1.7.2Realtime application framework (Node.JS server).
socket.io-client1.7.2Socket.io client.
splitargs0.0.7Splits strings into tokens by given separator except treating quoted part as a single token.
tingodb0.5.1Embedded Node.js database upward compatible with MongoDB.
tough-cookie2.3.2RFC6265 Cookies and Cookie Jar for node.js.
transducers-js0.4.174A high performance Transducers implementation for JavaScript.
type-is1.6.14Infer the content-type of a request.
watch0.18.0Utilities for watching file trees.
winston2.3.1A multi-transport async logging library for Node.js.
winston-daily-rotate-file1.4.4A multi-transport async logging library for Node.js.
xml2js0.4.16Simple XML to JavaScript object converter.

NOTE: The full SBT artifact expression is: "io.scalajs.npm" %%% "xxxx" % version (e.g. "io.scalajs.npm" %%% "express" % "0.5.0")

I've provided an example to demonstrate how similar the Scala.js code is to the JavaScript that it replaces.

The following is a simple Hello World app in Node using JavaScript:

var http = require("http");
http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
}).listen(8888);

Here's the same example using Scala.js:

import io.scalajs.nodejs.http._
import scalajs.js

Http.createServer((request: ClientRequest, response: ServerResponse) => {
    response.writeHead(200, js.Dictionary("Content-Type" -> "text/plain"))
    response.write("Hello World")
    response.end()
}).listen(8888)

Express.js

The following is a simple Hello World app in Node and Express using JavaScript:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
   res.send('Hello World');
})

var server = app.listen(8081, function () {
  var host = server.address().address
  var port = server.address().port
  console.log("Example app listening at http://%s:%s", host, port)
})

Here's the same example using Scala.js:

import io.scalajs.nodejs.console
import io.scalajs.npm.express._

val app = Express()

app.get("/", (req: Request, res: Response) => res.send("Hello World"))

val server = app.listen(8081, connect)

private def connect: js.Function = () => {
    val host = server.address().address
    val port = server.address().port
    console.log("Example app listening at http://%s:%s", host, port)
}

The following is a more elaborate example:

import io.scalajs.npm.express._
import io.scalajs.util.ScalaJsHelpers._
import scalajs.js

val todos: js.Array[Todo] = emptyArray

val app = Express()

app.use(BodyParser.json())
app.use(BodyParser.urlencoded(new UrlEncodedBodyOptions(extended = true)))   
 
app.get("/api/todo/:id", (request: Request, response: Response) => getTodo(request, response))
app.get("/api/todos", (request: Request, response: Response) => getTodos(request, response))
app.post("/api/todo", (request: Request, response: Response) => createTodo(request, response))

def createTodo(request: Request, response: Response) = {
    request.bodyAs[Todo] match {
        case todo if todo.hasTitle =>
            todo.id = UUID.randomUUID().toString
            todos.push(todo)
            response.send(todos)
        case todo =>
            response.badRequest(todo)
    }
}
  
def getTodo(request: Request, response: Response) = {
    val todoId = request.params("id")
    todos.indexWhereOpt(_.id == todoId) match {
        case Some(index) => response.send(todos(index))
        case None => response.notFound(todoId)
    }
}

def getTodos(request: Request, response: Response) = response.send(todos)

@js.native
trait Todo extends js.Object {
    var id: String = js.native
    var title: String = js.native
    var completed: Boolean = js.native
}

implicit class TodoExtensions(val todo: Todo) extends AnyVal {

    @inline
    def hasId: Boolean = Option(todo).flatMap(t => Option(t.id)).exists(_.trim.nonEmpty)
    
    @inline
    def hasTitle: Boolean = Option(todo).flatMap(t => Option(t.title)).exists(_.trim.nonEmpty)
    
    @inline
    def isComplete: Boolean = hasId && hasTitle

}

MongoDB

The following example demonstrates establishing a connection to MongoDB using Scala.js:

import io.scalajs.nodejs.console
import io.scalajs.npm.mongodb._
import io.scalajs.util.ScalaJsHelper._

// Connection URL. This is where your mongodb server is running.
val url = "mongodb://localhost:27017/test"

// Use connect method to connect to the Server
MongoClient.connect(url, (err, db) => {
    if (isDefined(err)) {
        console.log("Unable to connect to the mongoDB server. Error:", err)
    } else {
        // HURRAY!! We are connected. :)
        console.log("Connection established to: %s", url)
        
        // TODO do some work here with the database.
        
        // close connection
        db.close()
    }
})

Or, if you'd like to be more Scala idiomatic, the connection fragment could be written as follows:

import io.scalajs.nodejs.console
import io.scalajs.npm.mongodb._
import scala.util.{Success, Failure}

MongoClient.connectFuture(url) onComplete {
    case Success(db) =>
        // HURRAY!! We are connected. :)
        console.log("Connection established to: %s", url)

        // TODO do some work here with the database.

        // close connection
        db.close()
    case Failure(e) =>
        console.log("Unable to connect to the mongoDB server. Error:", e.getMessage)  
}

Alternatively, you could choose to use "foreach" to directly manage only the success case:

import io.scalajs.npm.mongodb._
import io.scalajs.util.PromiseHelper._

MongoClient.connectFuture(url) foreach { db => 
    // HURRAY!! We are connected. :)
    console.log("Connection established to: %s", url)

    // TODO do some work here with the database.

    // close connection
    db.close()
}

ScalaJs.io exposes Future-based alternatives to most of the asynchronous functions found in MongoDB, Express, Angular and Node. This means that you can use Scala's amazing for comprehensions to replace the dreaded pyramid of doom callbacks normally associated with JavaScript asynchronous code.

Consider the following:

for {
    // List all the virtual machine images you can use.
    vmImages <- computeManagementClient.virtualMachineVMImages.listFuture
    
    // Create a cloud service.
    computeManagementClient <- computeManagementClient.hostedServices.createFuture(
      HostedServicesOptions(serviceName = serviceName, label = "cloud service 01", location = "West US"))
    
    // Create a virtual machine in the cloud service
    deployment <- computeManagementClient.virtualMachines.createDeploymentFuture(serviceName, deploymentOptions)
} {
    console.info(deployment)
}
angular
mean-stack
mongodb
mongoose
node
nodejs
npm
scala
scala-bindings
scalajs

Contributors

ldaniels528

200 commits

rmmeans

3 commits

ScalaWilliam

1 commits

Languages

Scala

100.0%