Permalink
Browse files

initial version for review

  • Loading branch information...
1 parent ec4a54f commit 064e699f8239785f4b769a7a7b9315dd66af4269 @goulash1971 committed Jun 7, 2011
Showing with 405 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +3 −0 .gitmodules
  3. +3 −0 .npmignore
  4. +11 −0 Makefile
  5. +10 −0 index.js
  6. +74 −0 lib/index.js
  7. +120 −0 lib/plugins/resolveDBRefs.js
  8. +90 −0 lib/types/dbref.js
  9. +20 −0 lib/utils.js
  10. +33 −0 package.json
  11. +37 −0 tests/dbref.test.js
View
@@ -0,0 +1,4 @@
+.DS_Store
+material/
+node_modules/
+npm-debug.log
View
@@ -0,0 +1,3 @@
+[submodule "support/expresso"]
+ path = support/expresso
+ url = https://github.com/visionmedia/expresso.git
View
@@ -0,0 +1,3 @@
+.git*
+material/
+npm-debug.log
View
@@ -0,0 +1,11 @@
+EXPRESSO = support/expresso/bin/expresso -I lib
+
+TESTS = tests/*.test.js
+
+test:
+ @$(EXPRESSO) $(TESTS) $(TEST_FLAGS)
+
+test-cov:
+ @$(MAKE) TEST_FLAGS=--cov test
+
+.PHONY: test test-cov
View
@@ -0,0 +1,10 @@
+/*
+ * Module file for Mongoose-DBRef
+ *
+ * Copyright 2011, Stuart Hudson <goulash1971@yahoo.com>
+ * Released under the terms of the MIT License.
+ *
+ * Version 0.0.1
+ */
+
+module.exports = require("./lib");
View
@@ -0,0 +1,74 @@
+/**
+ * lib/index.js - module loader
+ *
+ * Copyright 2011, Stuart Hudson <goulash1971@yahoo.com>
+ * Released under the terms of the MIT License.
+ *
+ * Version 0.0.1
+ */
+
+
+/**
+ * Expose the utilities that are available from this module (these
+ * are also accessed from the loadTypes function.
+ */
+exports.utils = utils = require("./utils");
+
+
+/**
+ * Loads either the named types or all available types in the
+ * {@code lib/types} source directory
+ *
+ * @param {Mongoose} the active Mongoose instance for installation
+ * @param {Array} (optional) type filenames
+ */
+exports.loadTypes = loadTypes = function (mongoose) {
+ var types = Array.prototype.slice.call(arguments, 1);
+ if (types.length) {
+ types.forEach(function (type) {
+ require("./types/" + type).loadType(mongoose);
+ });
+ } else {
+ var files = require("fs").readdirSync(__dirname + "/types");
+ files.forEach(function(filename) {
+ var base = filename.slice(0, filename.length-3);
+ require("./types/" + base).loadType(mongoose);
+ });
+ }
+};
+
+
+/**
+ * Installs either the named plugins or all available plugins in the
+ * {@code lib/plugins} source directory
+ *
+ * @param {Mongoose} the active Mongoose instance for installation
+ * @param {Array} (optional) plugin filenames
+ */
+exports.installPlugins = installPlugins = function (mongoose) {
+ var plugins = Array.prototype.slice.call(arguments, 1);
+ if (plugins.length) {
+ types.forEach(function (plugin) {
+ require("./plugins/" + plugin).install(mongoose);
+ });
+ } else {
+ var files = require("fs").readdirSync(__dirname + "/plugins");
+ files.forEach(function(filename) {
+ var base = filename.slice(0, filename.length-3);
+ require("./plugins/" + base).install(mongoose);
+ });
+ }
+}
+
+/**
+ * Installation function that will load all of the types and install
+ * all of the plugins that are defined for this mongoose extension.
+ *
+ * @param {Mongoose} the active Mongoose instance for installation
+ * @return the utilities of the extension (see './utils.js')
+ */
+exports.install = function (mongoose) {
+ loadTypes (mongoose);
+ installPlugins(mongoose);
+ return utils;
+}
@@ -0,0 +1,120 @@
+/**
+ * lib/plugins/resolveDbRefs.js - DBRef Resolver
+ *
+ * Copyright 2011, Stuart Hudson <goulash1971@yahoo.com>
+ * Released under the terms of the MIT License.
+ *
+ * Version 0.0.1
+ */
+var mongoose = require("mongoose");
+
+/**
+ * Utility function that constructs a table of names for a given
+ * path.
+ *
+ * @param {String} the path name
+ * @return {Object} specifying the 'cache', 'getter' and 'setter'
+ */
+var namesForPath = function (path) {
+ var root = path.replace(/^[_]+/g,"");
+ var names = {cache: "$" + root};
+ root = root[0].toUpperCase() + root.slice(1);
+ names['getter'] = "get" + root;
+ names['setter'] = "set" + root;
+ return names;
+}
+
+
+/**
+ * Plugin that will create a getter/setter method pair for each path in
+ * a schema where the schema type is 'DBRef' and the 'resolve' flag true.
+ *
+ * The setter method will convert any 'Object' (model) passed into a
+ * database reference, and the getter method will resolve the stored
+ * database reference to an object using the connection of the owning
+ * model instance.
+ *
+ * The getter & setter methods use the path name as the root of the
+ * method signature (i.e. 'name' gives 'getName' & 'setName') but where
+ * the path is private (i.e. '_' prefix) this is stripped when creating
+ * the getter & setter (i.e. '_age' gives 'getAge' and 'setAge').
+ *
+ * If the 'cache' flag is set to true then resolved value is cached
+ * in a model property that has the path name prefixed with a '$'
+ * sign (i.e. 'name' cached in '$name' and '_age' cached in '$age').
+ *
+ * Each setter has one argument, the object to be set via reference
+ * or 'null' and the getter has 2 arguments, a callback function to be
+ * invoked after the value has been resolved and an optional boolean
+ * argument, 'force', that will ignore any cached value.
+ *
+ * @param {Object} the schema the plugin is being used against
+ * @param {Object} global options that apply to this plugin
+ */
+exports.resolveDBRefs = resolveDBRefs = function (schema, options) {
+ if (!('mongoose' in options))
+ throw new Error("'mongoose' option not defined");
+ if (!('DBRef' in options.mongoose.Types))
+ throw new Error("'DBRef' type not installed");
+ var dbref = options.mongoose.SchemaTypes.DBRef;
+ schema.eachPath(
+ function (path, defn) {
+ if (defn.options['type'] !== dbref) return;
+ if (defn.options['resolve'] === true) {
+ var names = namesForPath(path);
+ if (defn.options['cached'] === true) {
+ var cache = names['cache'];
+ schema.method(names['getter'], function(callback, force) {
+ var val = this[path];
+ if ((typeof val === 'undefined') || (val === null)) {
+ callback(null, null);
+ } else {
+ force = (force === true) ||
+ typeof this[cache] === 'undefined' ||
+ this[cache] === val;
+ if (!force) {
+ callback(null, this[cache]);
+ } else {
+ var self = this;
+ this.db.db.dereference(val, function(err, doc) {
+ self[cache] = doc; callback(err, doc) });
+ }
+ }
+ });
+ schema.method(names['setter'], function(value) {
+ this[cache] = value;
+ if (value !== null)
+ this[path] = dbref.prototype.cast(
+ {"$ref": value.collection.name,
+ "$id": value._id, "$db": value.db.db.databaseName});
+ else this[path] = null;
+ });
+ } else {
+ schema.method(names['getter'], function(callback) {
+ var val = this[path];
+ if ((typeof val === 'undefined') || (val === null))
+ callback(null, null);
+ else this.db.db.dereference(val, callback);
+ });
+ schema.method(names['setter'], function(value) {
+ if (value !== null)
+ this[path] = dbref.prototype.cast(
+ {"$ref": value.collection.name,
+ "$id": value._id, "$db": value.db.db.databaseName});
+ else this[path] = null;
+ });
+ }
+ }
+ });
+}
+
+
+
+/**
+ * Installer that installs a plugin into the mongoose infrastructure
+ *
+ * @param {Mongoose} the active Mongoose instance for installation
+ */
+exports.install = function (mongoose) {
+ return mongoose.plugin(resolveDBRefs, {mongoose: mongoose});
+}
View
@@ -0,0 +1,90 @@
+/**
+ * lib/types/dbref.js - the DBRef type
+ *
+ * Copyright 2011, Stuart Hudson <goulash1971@yahoo.com>
+ * Released under the terms of the MIT License.
+ *
+ * Version 0.0.1
+ */
+var mongoose = require("mongoose");
+
+/**
+ * Utility function that will cast a single object for a condition
+ *
+ * @param {Object} the single object to be handled
+ */
+function handleSingle (value) {
+ return this.cast(value);
+}
+
+/**
+ * Utility function that will cast an array for a condition
+ *
+ * @param {Array} the array of objects to be handled
+ */
+function handleArray (value) {
+ var self = this;
+ return value.map (function(m) {return self.cast(m);});
+}
+
+
+/**
+ * Loader that loads the type into the mongoose infrastructure
+ *
+ * @param {Mongoose} the active Mongoose instance for installation
+ */
+exports.loadType = function (mongoose) {
+ // The types that are used for schema and models
+ var SchemaType = mongoose.SchemaType;
+ var SchemaTypes = mongoose.SchemaTypes;
+
+ // The native type used for storage
+ var dbref = mongoose.mongo.BSONPure.DBRef;
+
+ // Constructor for schema type
+ function DBRef (value, options) {
+ SchemaType.call(this, value, options);
+ };
+
+ // Direct inheritence from schema type
+ DBRef.prototype.__proto__ = SchemaType.prototype;
+
+ // Testing method to evaluate whether check needed
+ DBRef.prototype.checkRequired = function (value) {
+ return !!value && value instanceof dbref;
+ };
+
+ // Casting function using raw or processed refs
+ DBRef.prototype.cast = function (value) {
+ var oid = SchemaTypes.ObjectId;
+ if (value === null) return value;
+ if (value instanceof dbref) return value;
+ if (typeof value !== 'object') throw new CastError('db reference', value);
+ return new dbref(value["$ref"], oid.prototype.cast(value["$id"]), value["$db"]);
+ };
+
+ // Condition handlers - glues condition to casting
+ DBRef.prototype.$conditionalHandlers = {
+ '$ne': handleSingle,
+ '$in': handleArray,
+ '$nin': handleArray
+ };
+
+ // Casting function used in queries & conditions
+ DBRef.prototype.castForQuery = function ($conditional, value) {
+ var handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler)
+ throw new Error("Can't use " + $conditional + " with DBRef.");
+ return handler.call(this, value);
+ } else {
+ value = $conditional;
+ return this.cast(value);
+ }
+ };
+
+ // Perform the installation
+ mongoose.SchemaTypes.DBRef = DBRef;
+ mongoose.Types.DBRef = dbref;
+}
View
@@ -0,0 +1,20 @@
+/**
+ * lib/utils.js - module utilities loader
+ *
+ * Copyright 2011, Stuart Hudson <goulash1971@yahoo.com>
+ * Released under the terms of the MIT License.
+ *
+ * Version 0.0.1
+ */
+
+/**
+ * Utility that will de-reference a DBRef using the database
+ * assciated with a given connection
+ *
+ * @param {Connection} a database connection
+ * @param {DBRef} a valid database reference instance
+ * @param {Function} standard callback '(err, doc)'
+ */
+exports.fetch = fetch = function (conn, dbref, callback) {
+ return conn.db.dereference(dbref, callback);
+}
View
@@ -0,0 +1,33 @@
+{
+ "name": "mongoose-dbref",
+ "private": true,
+ "description": "Plugin support for DBRef in Mongoose",
+ "version": "0.0.1",
+ "author": "Stuart Hudson <goulash1971@yahoo.com>",
+ "keywords": ["mongodb", "mongoose", "mongo", "types", "dbref"],
+ "homepage": "https://github.com/goulash1971/mongoose-dbref",
+ "contributors": [
+ "Stuart Hudson <goulash1971@yahoo.com> (http://goulash1971.com/)"
+ ],
+ "dependencies": {
+ "mongoose": ">= 1.0.16"
+ },
+ "scripts": {
+ "test": "make test"
+ },
+ "directories": {
+ "lib": "lib/",
+ "test": "tests/"
+ },
+ "main": "./index",
+ "engines": {
+ "node": ">= 0.1.101"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/goulash1971/mongoose-dbref.git"
+ },
+ "licenses": [
+ {"type": "The MIT License", "url": "http://www.opensource.org/licenses/mit-license.php"}
+ ]
+}
Oops, something went wrong.

0 comments on commit 064e699

Please sign in to comment.