Skip to content

Commit d41a7e6

Browse files
committed
Continued development
1. Moved string-decoder to a sub-project 2. Updated Express and internal HTTP modules 3. Enhanced the MongoDB module (added Mongo DSL)
1 parent 006f002 commit d41a7e6

39 files changed

+1876
-178
lines changed

README.md

+22-18
Original file line numberDiff line numberDiff line change
@@ -63,24 +63,28 @@ modules implemented for most web applications.
6363

6464
The following NodeJS modules have been implemented thus far:
6565

66-
* body-parser
67-
* buffer
68-
* events
69-
* express
70-
* express-ws
71-
* fs
72-
* http
73-
* https
74-
* kafka-node
75-
* mongodb
76-
* net
77-
* os
78-
* node-zookeeper-client
79-
* readline
80-
* repl
81-
* stream
82-
* url
83-
* util
66+
| Module | Artifact | Description |
67+
|-------------------|-----------------------|-------------|
68+
| body-parser | means-node-express | Node.js body parsing middleware. |
69+
| buffer | means-node-core |
70+
| events | means-node-core |
71+
| express | means-node-express |
72+
| express-ws | means-node-express |
73+
| fs | means-node-core |
74+
| http | means-node-core |
75+
| https | means-node-core |
76+
| kafka-node | means-node-kafkanode |
77+
| mongodb | means-node-mongodb |
78+
| net | means-node-core |
79+
| os | means-node-os |
80+
| node-zookeeper-client | means-node-zookeeper-client |
81+
| readline | means-node-core |
82+
| repl | means-node-repl |
83+
| stream | means-node-core |
84+
| string-decoder | means-node-string-decoder |
85+
| url | means-node-core |
86+
| util | means-node-core |
87+
| zlib | means-node-zlib |
8488

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

build.sbt

+22-5
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.1.1"
7+
val apiVersion = "0.1.2"
88
val paradisePluginVersion = "2.1.0"
99
val _scalaVersion = "2.11.8"
1010
val scalaJsDomVersion = "0.9.0"
@@ -15,19 +15,27 @@ val commonSettings = Seq(
1515
version := apiVersion,
1616
scalaVersion := _scalaVersion,
1717
scalacOptions ++= Seq("-feature", "-deprecation"),
18+
scalacOptions in (Compile, doc) ++= Seq(
19+
"-no-link-warnings" // Suppresses problems with Scaladoc @throws links
20+
),
1821
homepage := Some(url("http://github.com.ldaniels528/MEANS.js")),
1922
addCompilerPlugin("org.scalamacros" % "paradise" % paradisePluginVersion cross CrossVersion.full),
2023
libraryDependencies ++= Seq(
2124
"be.doeraene" %%% "scalajs-jquery" % scalaJsJQueryVersion,
2225
"org.scala-js" %%% "scalajs-dom" % scalaJsDomVersion,
23-
"org.scala-lang" % "scala-reflect" % _scalaVersion
26+
"org.scala-lang" % "scala-reflect" % _scalaVersion,
27+
//
28+
// Testing dependencies
29+
//
30+
"org.mockito" % "mockito-all" % "1.9.5" % "test",
31+
"org.scalatest" %% "scalatest" % "2.2.2" % "test"
2432
)
2533
)
2634

2735
lazy val root = (project in file(".")).
2836
aggregate(
2937
core, angularjs, facebook, linkedin,
30-
node_core, node_express, node_kafka, node_mongodb, node_os, node_repl, node_zlib, node_zookeeper
38+
node_core, node_express, node_kafka, node_mongodb, node_os, node_repl, node_string_decoder, node_zlib, node_zookeeper
3139
)
3240

3341
lazy val core = (project in file("core")).
@@ -119,6 +127,15 @@ lazy val node_repl = (project in file("node/repl")).
119127
description := "NodeJS/REPL facade for Scala.js"
120128
)
121129

130+
lazy val node_string_decoder = (project in file("node/string_decoder")).
131+
dependsOn(core, node_core).
132+
enablePlugins(ScalaJSPlugin).
133+
settings(commonSettings: _*).
134+
settings(
135+
name := "means-node-string-decoder",
136+
description := "NodeJS/REPL facade for Scala.js"
137+
)
138+
122139
lazy val node_zlib = (project in file("node/zlib")).
123140
dependsOn(core, node_core).
124141
enablePlugins(ScalaJSPlugin).
@@ -138,8 +155,8 @@ lazy val node_zookeeper = (project in file("node/node_zookeeper")).
138155
)
139156

140157
lazy val examples = (project in file("examples")).
141-
aggregate(core, node_core, node_express, node_kafka, node_mongodb, node_os, node_repl, node_zlib, node_zookeeper).
142-
dependsOn(core, node_core, node_express, node_kafka, node_mongodb, node_os, node_repl, node_zlib, node_zookeeper).
158+
aggregate(core, node_core, node_express, node_kafka, node_mongodb, node_os, node_repl, node_string_decoder, node_zlib, node_zookeeper).
159+
dependsOn(core, node_core, node_express, node_kafka, node_mongodb, node_os, node_repl, node_string_decoder, node_zlib, node_zookeeper).
143160
enablePlugins(ScalaJSPlugin).
144161
settings(commonSettings: _*).
145162
settings(

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ object PromiseHelper {
1515
// Monitoring Functions
1616
////////////////////////////////////////////////////////////////////////
1717

18-
def time[T](action: String, task: => Future[T], showHeader: Boolean = true)(implicit ec: ExecutionContext): Future[T] = {
18+
def time[T](action: String, task: => Future[T], showHeader: Boolean = false)(implicit ec: ExecutionContext): Future[T] = {
1919
if (showHeader) console.info(s"$action...")
2020
val startTime = System.currentTimeMillis()
2121
task onComplete {
2222
case Success(_) =>
23-
console.info(s"$action took ${System.currentTimeMillis() - startTime} msecs")
23+
val elapsedTime = System.currentTimeMillis - startTime
24+
console.info(f"$action took $elapsedTime msecs")
2425
case Failure(e) =>
25-
console.warn(s"$action failed after ${System.currentTimeMillis() - startTime} msecs")
26+
val elapsedTime = System.currentTimeMillis - startTime
27+
console.info(f"$action took $elapsedTime msecs")
2628
}
2729
task
2830
}

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

+12
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ object ScalaJsHelper {
3939
promise.future
4040
}
4141

42+
/**
43+
* Converts a JavaScript-style callback to a Scala-style future
44+
* @param f the given callback function
45+
* @return a Scala-style future
46+
*/
47+
@inline
48+
def callback2ToFuture[E <: js.Any, R](f: js.Function => Unit): Future[R] = {
49+
val promise = Promise[R]()
50+
f((err: E, result: R) => if (!isDefined(err)) promise.success(result) else promise.failure(wrapJavaScriptException(err)))
51+
promise.future
52+
}
53+
4254
/**
4355
* Converts a JavaScript-style callback to a Scala-style future
4456
* @param f the given callback function
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.github.ldaniels528.meansjs.nodejs
2+
3+
import scala.scalajs.js
4+
5+
/**
6+
* The console module provides a simple debugging console that is similar to the JavaScript console mechanism
7+
* provided by web browsers.
8+
*
9+
* The module exports two specific components:
10+
* <ul>
11+
* <li>A Console class with methods such as console.log(), console.error() and console.warn() that can be used to
12+
* write to any Node.js stream.</li>
13+
* <li>A global console instance configured to write to stdout and stderr. Because this object is global, it can be
14+
* used without calling require('console').</li>
15+
* </ul>
16+
17+
*/
18+
@js.native
19+
trait Console extends js.Object {
20+
21+
/**
22+
* A simple assertion test that verifies whether value is truthy. If it is not, an AssertionError is thrown.
23+
* If provided, the error message is formatted using util.format() and used as the error message.
24+
* @example console.assert(value[, message][, ...])
25+
*/
26+
def assert(value: js.Any, message: String, args: js.Any*): Unit = js.native
27+
28+
/**
29+
* A simple assertion test that verifies whether value is truthy. If it is not, an AssertionError is thrown.
30+
* If provided, the error message is formatted using util.format() and used as the error message.
31+
* @example console.assert(value[, message][, ...])
32+
*/
33+
def assert(value: js.Any, args: js.Any*): Unit = js.native
34+
35+
/**
36+
* Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and
37+
* all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
38+
* @param data the given data arguments
39+
* @example console.log([data][, ...])
40+
*/
41+
def log(data: js.Any, args: js.Any*): Unit = js.native
42+
43+
/**
44+
* Prints to stderr with newline. Multiple arguments can be passed, with the first used as the primary message and
45+
* all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
46+
* @param data the given data arguments
47+
* @example console.error([data][, ...])
48+
*/
49+
def error(data: js.Any, args: js.Any*): Unit = js.native
50+
51+
/**
52+
* The console.info() function is an alias for console.log().
53+
* @example console.info([data][, ...])
54+
*/
55+
def info(data: js.Any, args: js.Any*): Unit = js.native
56+
57+
/**
58+
* Starts a timer that can be used to compute the duration of an operation. Timers are identified by a unique label.
59+
* Use the same label when you call console.timeEnd() to stop the timer and output the elapsed time in milliseconds
60+
* to stdout. Timer durations are accurate to the sub-millisecond.
61+
* @example console.time(label)
62+
*/
63+
def time(label: String): Unit = js.native
64+
65+
/**
66+
* Stops a timer that was previously started by calling console.time() and prints the result to stdout
67+
* @example console.timeEnd(label)
68+
*/
69+
def timeEnd(label: String): Unit = js.native
70+
71+
/**
72+
* Prints to stderr the string 'Trace :', followed by the util.format() formatted message and stack trace to the
73+
* current position in the code.
74+
* @example console.trace(message[, ...])
75+
*/
76+
def trace(message: String, args: js.Any*): Unit = js.native
77+
78+
}

node/core/src/main/scala/com/github/ldaniels528/meansjs/nodejs/StringDecoder.scala

-14
This file was deleted.

node/core/src/main/scala/com/github/ldaniels528/meansjs/nodejs/http/Http.scala

+11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ trait Http extends NodeModule {
2222
*/
2323
def globalAgent: js.Array[js.Any] = js.native
2424

25+
/**
26+
* A list of the HTTP methods that are supported by the parser.
27+
*/
28+
val METHODS: js.Array[String] = js.native
29+
30+
/**
31+
* A collection of all the standard HTTP response status codes, and the short description of each.
32+
* @example http.STATUS_CODES[404] === 'Not Found'.
33+
*/
34+
val STATUS_CODES: js.Dictionary[String] = js.native
35+
2536
/////////////////////////////////////////////////////////////////////////////////
2637
// Methods
2738
/////////////////////////////////////////////////////////////////////////////////

node/core/src/main/scala/com/github/ldaniels528/meansjs/nodejs/http/IncomingMessage.scala

+96
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.github.ldaniels528.meansjs.nodejs.http
22

3+
import com.github.ldaniels528.meansjs.nodejs.net.Socket
34
import com.github.ldaniels528.meansjs.nodejs.stream
45

6+
import scala.concurrent.duration.FiniteDuration
57
import scala.scalajs.js
68

79
/**
@@ -14,4 +16,98 @@ import scala.scalajs.js
1416
@js.native
1517
trait IncomingMessage extends stream.Readable {
1618

19+
/**
20+
* The request/response headers object. Key-value pairs of header names and values. Header names are lower-cased.
21+
* @example message.headers
22+
*/
23+
def headers: js.Dictionary[String] = js.native
24+
25+
/**
26+
* In case of server request, the HTTP version sent by the client. In the case of client response,
27+
* the HTTP version of the connected-to server. Probably either '1.1' or '1.0'.
28+
* @example message.httpVersion
29+
*/
30+
def httpVersion: String = js.native
31+
32+
/**
33+
* Only valid for request obtained from http.Server. The request method as a string. Read only. Example: 'GET', 'DELETE'.
34+
* @example message.method
35+
*/
36+
def method: String = js.native
37+
38+
/**
39+
* The raw request/response headers list exactly as they were received. <b>Note</b> that the keys and values are
40+
* in the same list. It is not a list of tuples. So, the even-numbered offsets are key values, and the odd-numbered
41+
* offsets are the associated values. Header names are not lowercased, and duplicates are not merged.
42+
* @example message.rawHeaders
43+
*/
44+
def rawHeaders: js.Array[String] = js.native
45+
46+
/**
47+
* The raw request/response trailer keys and values exactly as they were received. Only populated at the 'end' event.
48+
* @example message.rawTrailers
49+
*/
50+
def rawTrailers: js.Array[String] = js.native
51+
52+
/**
53+
* Calls message.connection.setTimeout(msecs, callback).
54+
* @example message.setTimeout(msecs, callback)
55+
*/
56+
def setTimeout(msecs: Number, callback: js.Function): Unit = js.native
57+
58+
/**
59+
* Only valid for response obtained from http.ClientRequest. The 3-digit HTTP response status code (e.g. 404).
60+
* @example message.statusCode
61+
*/
62+
def statusCode: Int = js.native
63+
64+
/**
65+
* Only valid for response obtained from http.ClientRequest. The HTTP response status message (reason phrase)
66+
* (e.g. OK or Internal Server Error).
67+
* @example message.statusMessage
68+
*/
69+
def statusMessage: String = js.native
70+
71+
/**
72+
* The net.Socket object associated with the connection. With HTTPS support, use request.socket.getPeerCertificate()
73+
* to obtain the client's authentication details.
74+
* @example message.socket
75+
*/
76+
def socket: Socket = js.native
77+
78+
/**
79+
* The request/response trailers object. Only populated at the 'end' event.
80+
* @example message.trailers
81+
*/
82+
def trailers: js.Array[String] = js.native
83+
84+
/**
85+
* Only valid for request obtained from http.Server. Request URL string. This contains only the URL that is
86+
* present in the actual HTTP request.
87+
* @example message.url
88+
*/
89+
def url: String = js.native
90+
1791
}
92+
93+
/**
94+
* Incoming Message Companion
95+
96+
*/
97+
object IncomingMessage {
98+
99+
/**
100+
* Incoming Message Extensions
101+
102+
*/
103+
implicit class IncomingMessageExtensions(val message: IncomingMessage) extends AnyVal {
104+
105+
@inline
106+
def onClose(callback: js.Function) = message.on("close", callback)
107+
108+
@inline
109+
def setTimeout(duration: FiniteDuration, callback: js.Function) = message.setTimeout(duration.toMillis, callback)
110+
111+
}
112+
113+
}

0 commit comments

Comments
 (0)