Skip to content

Commit 006f002

Browse files
committed
Drastically improved the quality of the MongoDB module facade
1 parent 8a9f344 commit 006f002

File tree

97 files changed

+3268
-331
lines changed

Some content is hidden

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

97 files changed

+3268
-331
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ The following example demonstrates establishing a connection to MongoDB using Sc
193193
val url = "mongodb://localhost:27017/test"
194194

195195
// Use connect method to connect to the Server
196-
mongoClient.connect(url, (err: MongoError, db: MongoDatabase) => {
197-
if (err.isDefined) {
196+
mongoClient.connect(url, (err: js.Object, db: MongoDatabase) => {
197+
if (isDefined(err) {
198198
console.log("Unable to connect to the mongoDB server. Error:", err)
199199
} else {
200200
//HURRAY!! We are connected. :)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.github.ldaniels528.meansjs.angularjs
2+
3+
import scala.scalajs.js.JSON
4+
5+
/**
6+
* AngularJS Convenience Helper Functions
7+
8+
*/
9+
object AngularJsHelper {
10+
private val HttpError = "Failed to process HTTP request:"
11+
12+
/**
13+
* Exception Extensions
14+
* @param cause the given [[Throwable exception]]
15+
16+
*/
17+
implicit class ExceptionExtensions(val cause: Throwable) extends AnyVal {
18+
19+
@inline
20+
def displayMessage = Option(cause.getMessage) match {
21+
case Some(s) if s.startsWith(HttpError) => cleanUp(s.drop(HttpError.length))
22+
case Some(s) => s
23+
case None => "Cause unknown"
24+
}
25+
26+
private def cleanUp(s: String) = s.replaceAllLiterally("\"", "").replaceAllLiterally("'", "")
27+
28+
}
29+
30+
/**
31+
* Convenience methods for strings
32+
* @param string the given host string
33+
*/
34+
implicit class StringExtensions(val string: String) extends AnyVal {
35+
36+
@inline
37+
def indexOfOpt(substring: String): Option[Int] = Option(string).map(_.indexOf(substring)) flatMap {
38+
case -1 => None
39+
case index => Some(index)
40+
}
41+
42+
@inline def isValidEmail: Boolean = {
43+
string.matches("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")
44+
}
45+
46+
@inline def parseAs[T] = JSON.parse(string).asInstanceOf[T]
47+
48+
}
49+
50+
}

build.sbt

Lines changed: 1 addition & 1 deletion
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.0"
7+
val apiVersion = "0.1.1"
88
val paradisePluginVersion = "2.1.0"
99
val _scalaVersion = "2.11.8"
1010
val scalaJsDomVersion = "0.9.0"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.github.ldaniels528.meansjs.util
2+
3+
import org.scalajs.dom._
4+
5+
import scala.concurrent.{ExecutionContext, Future}
6+
import scala.util.{Failure, Success}
7+
8+
/**
9+
* Promise Helper
10+
11+
*/
12+
object PromiseHelper {
13+
14+
////////////////////////////////////////////////////////////////////////
15+
// Monitoring Functions
16+
////////////////////////////////////////////////////////////////////////
17+
18+
def time[T](action: String, task: => Future[T], showHeader: Boolean = true)(implicit ec: ExecutionContext): Future[T] = {
19+
if (showHeader) console.info(s"$action...")
20+
val startTime = System.currentTimeMillis()
21+
task onComplete {
22+
case Success(_) =>
23+
console.info(s"$action took ${System.currentTimeMillis() - startTime} msecs")
24+
case Failure(e) =>
25+
console.warn(s"$action failed after ${System.currentTimeMillis() - startTime} msecs")
26+
}
27+
task
28+
}
29+
30+
/**
31+
* Time Measurement Extensions
32+
* @param task the given [[Future task]]
33+
* @tparam T the return type of the task
34+
*/
35+
implicit class TimeExtensions[T](val task: Future[T]) extends AnyVal {
36+
37+
def withTimer(action: String, showHeader: Boolean = false)(implicit ec: ExecutionContext) = time(action, task, showHeader)
38+
39+
}
40+
41+
}

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

Lines changed: 17 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
package com.github.ldaniels528.meansjs.util
22

3-
import org.scalajs.dom.console
4-
5-
import scala.concurrent.{ExecutionContext, Future, Promise}
3+
import scala.concurrent.{Future, Promise}
64
import scala.language.implicitConversions
75
import scala.scalajs.js
8-
import scala.scalajs.js.JSON
96
import scala.scalajs.runtime.wrapJavaScriptException
10-
import scala.util.{Failure, Success, Try}
117

128
/**
13-
* Scala.js Convenience Helper Functions
9+
* ScalaJS Convenience Helper Functions
1410
1511
*/
1612
object ScalaJsHelper {
17-
private val HttpError = "Failed to process HTTP request:"
1813

1914
////////////////////////////////////////////////////////////////////////
2015
// Convenience Functions
2116
////////////////////////////////////////////////////////////////////////
2217

18+
/**
19+
* Converts a JavaScript-style callback to a Scala-style future
20+
* @param f the given callback function
21+
* @return a Scala-style future
22+
*/
23+
@inline
24+
def callbackToFuture[A](f: js.Function => Unit): Future[A] = {
25+
val promise = Promise[A]()
26+
f((result: A) => promise.success(result))
27+
promise.future
28+
}
29+
2330
/**
2431
* Converts a JavaScript-style callback to a Scala-style future
2532
* @param f the given callback function
@@ -44,90 +51,17 @@ object ScalaJsHelper {
4451
promise.future
4552
}
4653

47-
@inline
48-
def emptyArray[T] = js.Array[T]()
49-
50-
@inline
51-
def New[T <: js.Any] = new js.Object().asInstanceOf[T]
52-
53-
////////////////////////////////////////////////////////////////////////
54-
// Error-Handling Functions
55-
////////////////////////////////////////////////////////////////////////
56-
57-
/**
58-
* Exception Extensions
59-
* @param cause the given [[Throwable exception]]
60-
61-
*/
62-
implicit class ExceptionExtensions(val cause: Throwable) extends AnyVal {
63-
64-
@inline
65-
def displayMessage = Option(cause.getMessage) match {
66-
case Some(s) if s.startsWith(HttpError) => cleanUp(s.drop(HttpError.length))
67-
case Some(s) => s
68-
case None => "Cause unknown"
69-
}
70-
71-
private def cleanUp(s: String) = s.replaceAllLiterally("\"", "").replaceAllLiterally("'", "")
72-
73-
}
74-
75-
////////////////////////////////////////////////////////////////////////
76-
// Monitoring Functions
77-
////////////////////////////////////////////////////////////////////////
78-
79-
def time[T](action: String, task: => Future[T], showHeader: Boolean = true)(implicit ec: ExecutionContext): Future[T] = {
80-
if (showHeader) console.info(s"$action...")
81-
val startTime = System.currentTimeMillis()
82-
task onComplete {
83-
case Success(_) =>
84-
console.info(s"$action took ${System.currentTimeMillis() - startTime} msecs")
85-
case Failure(e) =>
86-
console.warn(s"$action failed after ${System.currentTimeMillis() - startTime} msecs")
87-
}
88-
task
89-
}
90-
91-
/**
92-
* Time Measurement Extensions
93-
* @param task the given [[Future task]]
94-
* @tparam T the return type of the task
95-
*/
96-
implicit class TimeExtensions[T](val task: Future[T]) extends AnyVal {
97-
98-
def withTimer(action: String, showHeader: Boolean = true)(implicit ec: ExecutionContext) = time(action, task, showHeader)
99-
100-
}
101-
102-
////////////////////////////////////////////////////////////////////////
103-
// Validation Functions
104-
////////////////////////////////////////////////////////////////////////
105-
10654
@inline
10755
def die[T](message: String): T = throw new IllegalStateException(message)
10856

10957
@inline
110-
def isDefined(obj: js.Any) = obj != null && !js.isUndefined(obj)
111-
112-
@inline
113-
def isDefined(fx: js.Function) = fx != null && !js.isUndefined(fx)
114-
115-
@inline
116-
def isFalse(obj: js.Dynamic) = !isTrue(obj)
117-
118-
@inline
119-
def isTrue(obj: js.Dynamic) = isDefined(obj) && obj.as[Boolean]
120-
121-
@inline
122-
def required(name: String, value: String) = if (value == null || value.trim.isEmpty) die(s"Required property '$name' is missing")
58+
def emptyArray[T] = js.Array[T]()
12359

12460
@inline
125-
def required(name: String, value: js.Any) = if (!isDefined(value)) die(s"Required property '$name' is missing")
61+
def isDefined(obj: js.Any) = obj != null && !js.isUndefined(obj)
12662

12763
@inline
128-
def required[T](name: String, value: js.Array[T], allowEmpty: Boolean = false) = {
129-
if (value == null || (allowEmpty && value.isEmpty)) die(s"Required property '$name' is missing")
130-
}
64+
def New[T <: js.Any] = new js.Object().asInstanceOf[T]
13165

13266
////////////////////////////////////////////////////////////////////////
13367
// Implicit Definitions and Classes
@@ -144,31 +78,10 @@ object ScalaJsHelper {
14478
js.Dynamic.newInstance(obj.asInstanceOf[js.Dynamic])(args: _*).asInstanceOf[T]
14579
}
14680

147-
@inline
148-
def ===[T](value: T): Boolean = {
149-
if (value == null) !isDefined(obj)
150-
else {
151-
Try(obj.asInstanceOf[T]) match {
152-
case Success(converted) => converted == value
153-
case Failure(e) =>
154-
console.log(s"JsDynamicExtensionsA: value '$value': ${e.getMessage}")
155-
false
156-
}
157-
}
158-
}
159-
160-
@inline def as[T] = if (isDefined(obj)) obj.asInstanceOf[T] else null.asInstanceOf[T]
161-
16281
@inline def asOpt[T] = obj.asInstanceOf[js.UndefOr[T]].toOption
16382

164-
@inline def asArray[T] = obj.asInstanceOf[js.Array[T]]
165-
16683
@inline def dynamic = obj.asInstanceOf[js.Dynamic]
16784

168-
@inline def isTrue = isDefined(obj) && Try(obj.asInstanceOf[Boolean]).toOption.contains(true)
169-
170-
@inline def toUndefOr[T]: js.UndefOr[T] = obj.asInstanceOf[js.UndefOr[T]]
171-
17285
}
17386

17487
/**
@@ -197,26 +110,6 @@ object ScalaJsHelper {
197110
}
198111
}
199112

200-
/**
201-
* Value to js.Dynamic Extensions
202-
* @param value the given [[String value]]
203-
*/
204-
implicit class JsDynamicExtensions(val value: String) extends AnyVal {
205-
206-
@inline
207-
def ===(obj: js.Dynamic): Boolean = {
208-
if (!isDefined(obj)) value == null
209-
else {
210-
Try(obj.asInstanceOf[String]) match {
211-
case Success(converted) => converted == value
212-
case Failure(e) =>
213-
console.log(s"JsDynamicExtensionsB: value '$value': ${e.getMessage}")
214-
false
215-
}
216-
}
217-
}
218-
}
219-
220113
/**
221114
* Option Extensions
222115
* @param valueA the given [[Option option]]
@@ -233,24 +126,6 @@ object ScalaJsHelper {
233126

234127
}
235128

236-
/**
237-
* Convenience methods for strings
238-
* @param string the given host string
239-
*/
240-
implicit class StringExtensions(val string: String) extends AnyVal {
241-
242-
@inline
243-
def indexOfOpt(substring: String): Option[Int] = Option(string).map(_.indexOf(substring)) flatMap {
244-
case -1 => None
245-
case index => Some(index)
246-
}
247-
248-
@inline def isValidEmail: Boolean = string.matches("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")
249-
250-
@inline def parseAs[T] = JSON.parse(string).asInstanceOf[T]
251-
252-
}
253-
254129
/**
255130
* UndefOr Extensions
256131
* @param valueA the given [[js.UndefOr undefined or otherwise value]]

examples/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
"express": "4.13.4",
1010
"express-ws": "^2.0.0-beta",
1111
"fs": "0.0.2",
12+
"gridfs-stream": "^1.1.1",
1213
"html": "0.0.10",
1314
"kafka-node": "^0.3.2",
14-
"mongoose": "4.4.11",
15+
"mongodb": "^2.1.18",
1516
"node-zookeeper-client": "^0.2.2",
1617
"readline": "^1.3.0"
1718
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* GridFS Bucket Example
3+
4+
*/
5+
(function() {
6+
7+
var assert = require('assert');
8+
var fs = require('fs');
9+
var mongodb = require('mongodb');
10+
11+
var uri = 'mongodb://localhost:27017/test';
12+
13+
mongodb.MongoClient.connect(uri, function(error, db) {
14+
assert.ifError(error);
15+
16+
var bucket = new mongodb.GridFSBucket(db);
17+
18+
fs.createReadStream('/tmp/kickin_combo_2.jpg').
19+
pipe(bucket.openUploadStream('meistersinger.mp3')).
20+
on('error', function(error) {
21+
assert.ifError(error);
22+
}).
23+
on('finish', function() {
24+
console.log('done!');
25+
process.exit(0);
26+
});
27+
});
28+
29+
})();

0 commit comments

Comments
 (0)