Skip to content

Commit 48191fb

Browse files
committed
Continued development
1. Added the "repl" module 2. Refactored the events module 3. Refactored the stream module 4. Refactored JavaScript callback to Scala Future extensions 5. Updated examples
1 parent f96367e commit 48191fb

File tree

83 files changed

+2143
-1325
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+2143
-1325
lines changed

build.sbt

+13-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import sbt.Keys._
44
import sbt.Project.projectToRef
55
import sbt._
66

7-
val apiVersion = "0.0.7"
7+
val apiVersion = "0.0.8"
88
val paradisePluginVersion = "2.1.0"
99
val _scalaVersion = "2.11.8"
1010
val scalaJsDomVersion = "0.9.0"
@@ -25,7 +25,7 @@ val commonSettings = Seq(
2525
)
2626

2727
lazy val root = (project in file(".")).
28-
aggregate(core, angularjs, express, facebook, kafka_node, linkedin, mongodb, nodejs)
28+
aggregate(core, angularjs, express, facebook, kafka_node, linkedin, mongodb, node_zookeeper, nodejs, repl)
2929

3030
lazy val core = (project in file("core")).
3131
enablePlugins(ScalaJSPlugin).
@@ -107,9 +107,18 @@ lazy val node_zookeeper = (project in file("node_zookeeper")).
107107
description := "Zookeeper client bindings for Scala.js"
108108
)
109109

110+
lazy val repl = (project in file("repl")).
111+
dependsOn(core, nodejs).
112+
enablePlugins(ScalaJSPlugin).
113+
settings(commonSettings: _*).
114+
settings(
115+
name := "means-node-repl",
116+
description := "REPL bindings for Scala.js"
117+
)
118+
110119
lazy val examples = (project in file("examples")).
111-
aggregate(core, express, kafka_node, mongodb, nodejs, node_zookeeper).
112-
dependsOn(core, express, kafka_node, mongodb, nodejs, node_zookeeper).
120+
aggregate(core, express, kafka_node, mongodb, nodejs, node_zookeeper, repl).
121+
dependsOn(core, express, kafka_node, mongodb, nodejs, node_zookeeper, repl).
113122
enablePlugins(ScalaJSPlugin).
114123
settings(commonSettings: _*).
115124
settings(

core/src/main/scala/com/github/ldaniels528/meansjs/util/ScalaJsHelper.scala

+14-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package com.github.ldaniels528.meansjs.util
22

33
import org.scalajs.dom.console
44

5-
import scala.concurrent.{ExecutionContext, Future}
5+
import scala.concurrent.{ExecutionContext, Future, Promise}
66
import scala.language.implicitConversions
77
import scala.scalajs.js
88
import scala.scalajs.js.Dynamic.{global => g}
99
import scala.scalajs.js.JSON
10+
import scala.scalajs.runtime.wrapJavaScriptException
1011
import scala.util.{Failure, Success, Try}
1112

1213
/**
@@ -31,6 +32,18 @@ object ScalaJsHelper {
3132
if (queryString.nonEmpty) "?" + queryString else queryString
3233
}
3334

35+
/**
36+
* Converts a JavaScript-style callback to a Scala-style future
37+
* @param f the given callback function
38+
* @tparam T the return type
39+
* @return a Scala-style future
40+
*/
41+
def toFuture[T](f: js.Function => Unit): Future[T] = {
42+
val promise = Promise[T]()
43+
f((err: js.Any, result: T) => if (!isDefined(err)) promise.success(result) else promise.failure(wrapJavaScriptException(err)))
44+
promise.future
45+
}
46+
3447
////////////////////////////////////////////////////////////////////////
3548
// Error-Handling Functions
3649
////////////////////////////////////////////////////////////////////////

examples/examples.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
(function () {
66
require("./target/scala-2.11/means-examples-fastopt.js");
7-
var facade = examples.Examples();
7+
const facade = examples.Examples();
88
facade.start(require);
99
})();
1010

examples/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"html": "0.0.10",
1313
"kafka-node": "^0.3.2",
1414
"mongoose": "4.4.11",
15-
"node-zookeeper-client": "^0.2.2"
15+
"node-zookeeper-client": "^0.2.2",
16+
"readline": "^1.3.0"
1617
}
1718
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Net Server Example
3+
4+
*/
5+
(function () {
6+
7+
const net = require('net');
8+
9+
const client = net.connect({port: 8124}, function () {
10+
console.log('connected to server!');
11+
client.write('world!\r\n');
12+
});
13+
14+
client.on('data', function (data) {
15+
console.log(data.toString());
16+
client.end();
17+
});
18+
19+
client.on('end', function () {
20+
console.log('disconnected from server');
21+
});
22+
23+
})();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* REPL Example
3+
4+
*/
5+
(function () {
6+
7+
var net = require("net"),
8+
repl = require("repl");
9+
10+
var mood = function () {
11+
var m = ["^__^", "-___-;", ">.<", "<_>"];
12+
return m[Math.floor(Math.random() * m.length)];
13+
};
14+
15+
//A remote node repl that you can telnet to!
16+
net.createServer(function (socket) {
17+
var remote = repl.start("node::remote> ", socket);
18+
//Adding "mood" and "bonus" to the remote REPL's context.
19+
remote.context.mood = mood;
20+
remote.context.bonus = "UNLOCKED";
21+
}).listen(5001);
22+
23+
console.log("Remote REPL started on port 5001.");
24+
25+
//A "local" node repl with a custom prompt
26+
var local = repl.start("node::local> ");
27+
28+
// Exposing the function "mood" to the local REPL's context.
29+
local.context.mood = mood;
30+
31+
})();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Tiny CLI
3+
4+
*/
5+
(function () {
6+
7+
const readline = require('readline');
8+
const rl = readline.createInterface(process.stdin, process.stdout);
9+
10+
rl.setPrompt('OHAI> ');
11+
rl.prompt();
12+
13+
rl.on('line', function (line) {
14+
switch (line.trim()) {
15+
case 'hello':
16+
console.log('world!');
17+
break;
18+
default:
19+
console.log('Say what? I might have heard `' + line.trim() + '`');
20+
break;
21+
}
22+
rl.prompt();
23+
24+
}).on('close', function () {
25+
console.log('Have a great day!');
26+
process.exit(0);
27+
});
28+
29+
})();
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package examples
22

33
import com.github.ldaniels528.meansjs.nodejs._
4-
import examples.nodejs.{buffers, events, express, http, kafka, mongodb, net, timers, zookeeper}
4+
import examples.nodejs.{basics, buffers, events, express, http, kafka, mongodb, net, repl, timers, zookeeper}
55
import org.scalajs.dom.console
66

77
import scala.scalajs.js
@@ -13,29 +13,44 @@ import scala.scalajs.js.annotation.JSExportAll
1313
*/
1414
@JSExportAll
1515
object Examples extends js.JSApp {
16-
private val names = js.Array(
17-
"Buffers", "EventEmitting", "ExpressTest", "HttpServerTest", "IntermediateTimers", "MongoClientTest",
18-
"NetServerTest", "ProducerExample", "ProducerEnhanced", "TransactionExample"
16+
private val examples = js.Array(
17+
"Buffers", "EventEmitterExample", "ExpressRoutingExample", "ExpressServerExample",
18+
"HttpServerExample", "IntermediateTimers", "MongoClientExample", "NetServerExample",
19+
"ProducerExample", "ProducerEnhanced", "REPLExample", "TinyCLI", "TransactionExample"
1920
)
2021

2122
override def main(): Unit = ()
2223

23-
def start(require: Require) = {
24-
process.argv.drop(2) foreach {
25-
case "Buffers" => new buffers.Buffers(require)
26-
case "EventEmitting" => new events.EventEmitting(require)
27-
case "ExpressTest" => new express.ExpressTest(require)
28-
case "HttpServerTest" => new http.HttpServerTest(require)
29-
case "IntermediateTimers" => new timers.IntermediateTimers(require)
30-
case "MongoClientTest" => new mongodb.MongoClientTest(require)
31-
case "NetServerTest" => new net.NetServerTest(require)
32-
case "ProducerExample" => new kafka.ProducerExample(require)
33-
case "ProducerEnhanced" => new kafka.ProducerEnhanced(require)
34-
case "StateExample" => new zookeeper.StateExample(require)
35-
case "TransactionExample" => new zookeeper.TransactionExample(require)
36-
case arg =>
37-
console.warn(s"Syntax: examples.js <exampleName> - Choose one: ${names.mkString(", ")}")
24+
def start(require: Require) {
25+
val args = process.argv.drop(2)
26+
if (args.isEmpty) usageError()
27+
else {
28+
args map { arg => console.log(s"Executing example '$arg'"); arg } foreach {
29+
case "Buffers" => new buffers.Buffers(require)
30+
case "Classes" => new basics.Classes(require)
31+
case "EventEmitterExample" => new events.EventEmitterExample(require)
32+
case "ExpressRoutingExample" => new express.ExpressRoutingExample(require)
33+
case "ExpressServerExample" => new express.ExpressServerExample(require)
34+
case "HttpServerExample" => new http.HttpServerExample(require)
35+
case "IntermediateTimers" => new timers.IntermediateTimers(require)
36+
case "MongoClientExample" => new mongodb.MongoClientExample(require)
37+
case "NetServerExample" => new net.NetServerExample(require)
38+
case "ProducerExample" => new kafka.ProducerExample(require)
39+
case "ProducerEnhanced" => new kafka.ProducerEnhanced(require)
40+
case "REPLExample" => new repl.REPLExample(require)
41+
case "StateExample" => new zookeeper.StateExample(require)
42+
case "TinyCLI" => new repl.TinyCLI(require)
43+
case "TransactionExample" => new zookeeper.TransactionExample(require)
44+
case arg => usageError()
45+
}
3846
}
3947
}
4048

49+
def usageError(): Unit = {
50+
val choices = examples.sliding(4, 4) map (_.mkString(", ")) mkString "\n"
51+
console.warn("Usage: examples.js <example1>[, <example2>[, <exampleN>]]\n")
52+
console.log("Choose any of the following:")
53+
console.log(choices)
54+
}
55+
4156
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package examples.nodejs.basics
2+
3+
import com.github.ldaniels528.meansjs.nodejs.Require
4+
import org.scalajs.dom.console
5+
6+
import scala.scalajs.js
7+
import scala.scalajs.js.annotation.{JSName, ScalaJSDefined}
8+
9+
/**
10+
* Classes
11+
12+
*/
13+
class Classes(require: Require) {
14+
15+
val ralph = new Person()
16+
ralph.name = "Ralph"
17+
ralph.age = 32
18+
19+
console.log("ralph = %j", ralph)
20+
21+
}
22+
23+
@ScalaJSDefined
24+
@JSName("Person")
25+
class Person extends js.Object {
26+
var name: String = _
27+
var age: Int = _
28+
}
29+

examples/src/main/scala/examples/nodejs/events/EventEmitting.scala renamed to examples/src/main/scala/examples/nodejs/events/EventEmitterExample.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package examples.nodejs.events
22

33
import com.github.ldaniels528.meansjs.nodejs._
4-
import com.github.ldaniels528.meansjs.nodejs.events.EventEmitter
4+
import com.github.ldaniels528.meansjs.nodejs.events.Events
55

66
/**
77
* Event Emitting Example
88
99
*/
10-
class EventEmitting(require: Require) {
11-
val eventEmitter = require[EventEmitter]("events")
10+
class EventEmitterExample(require: Require) {
11+
val eventEmitter = require[Events]("events")
1212
val ee = eventEmitter()
1313

1414
setImmediate(() => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package examples.nodejs.express
2+
3+
import com.github.ldaniels528.meansjs.nodejs._
4+
import com.github.ldaniels528.meansjs.nodejs.express._
5+
import org.scalajs.dom.console
6+
7+
import scala.scalajs.js
8+
9+
/**
10+
* Express Routing Example
11+
12+
*/
13+
class ExpressRoutingExample(require: Require) {
14+
15+
val express = require[Express]("express")
16+
val app = express()
17+
val server = app.listen(8081, connect)
18+
19+
// This responds with "Hello World" on the homepage
20+
app.get("/", (req: Request, res: Response) => {
21+
console.log("Got a GET request for the homepage")
22+
res.send("Hello GET")
23+
})
24+
25+
// This responds a POST request for the homepage
26+
app.post("/", (req: Request, res: Response) => {
27+
console.log("Got a POST request for the homepage")
28+
res.send("Hello POST")
29+
})
30+
31+
// This responds a DELETE request for the /del_user page.
32+
app.delete("/del_user", (req: Request, res: Response) => {
33+
console.log("Got a DELETE request for /del_user")
34+
res.send("Hello DELETE")
35+
})
36+
37+
// This responds a GET request for the /list_user page.
38+
app.get("/list_user", (req: Request, res: Response) => {
39+
console.log("Got a GET request for /list_user")
40+
res.send("Page Listing")
41+
})
42+
43+
// This responds a GET request for abcd, abxcd, ab123cd, and so on
44+
app.get("/ab*cd", (req: Request, res: Response) => {
45+
console.log("Got a GET request for /ab*cd")
46+
res.send("Page Pattern Match")
47+
})
48+
49+
private def connect: js.Function = () => {
50+
val host = server.address().address
51+
val port = server.address().port
52+
53+
console.log("Example app listening at http://%s:%s", host, port)
54+
}
55+
56+
}

0 commit comments

Comments
 (0)