1
0
Fork 0
arangodb/js/server/modules/@arangodb/foxx/legacy/repository.js

433 lines
16 KiB
JavaScript

'use strict';
// //////////////////////////////////////////////////////////////////////////////
// / DISCLAIMER
// /
// / Copyright 2013-2014 triAGENS GmbH, Cologne, Germany
// / Copyright 2015 ArangoDB GmbH, Cologne, Germany
// /
// / Licensed under the Apache License, Version 2.0 (the "License")
// / you may not use this file except in compliance with the License.
// / You may obtain a copy of the License at
// /
// / http://www.apache.org/licenses/LICENSE-2.0
// /
// / Unless required by applicable law or agreed to in writing, software
// / distributed under the License is distributed on an "AS IS" BASIS,
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// / See the License for the specific language governing permissions and
// / limitations under the License.
// /
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
// /
// / @author Lucas Dohmen
// / @author Alan Plum
// //////////////////////////////////////////////////////////////////////////////
const Model = require('@arangodb/foxx/legacy/model').Model;
const _ = require('lodash');
const extend = require('@arangodb/extend').extend;
const EventEmitter = require('events').EventEmitter;
const EVENTS = [
'beforeSave', 'beforeCreate', 'beforeUpdate', 'beforeRemove',
'afterSave', 'afterCreate', 'afterUpdate', 'afterRemove'
];
function Repository (collection, opts) {
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_initializer
// //////////////////////////////////////////////////////////////////////////////
this.options = opts || {};
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_collection
// //////////////////////////////////////////////////////////////////////////////
this.collection = collection;
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_model
// //////////////////////////////////////////////////////////////////////////////
this.model = this.options.model || Model;
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_modelSchema
// //////////////////////////////////////////////////////////////////////////////
Object.defineProperty(this, 'modelSchema', {
configurable: false,
enumerable: true,
get() {
return this.model.prototype.schema;
}
});
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_prefix
// //////////////////////////////////////////////////////////////////////////////
this.prefix = this.options.prefix;
// Undocumented, unfinished graph feature
this.graph = this.options.graph;
if (this.indexes) {
_.each(this.indexes, function (index) {
this.collection.ensureIndex(index);
}.bind(this));
}
EventEmitter.call(this);
Object.keys(this.model).forEach(function (eventName) {
const listener = this.model[eventName];
if (EVENTS.indexOf(eventName) === -1 || typeof listener !== 'function') {
return;
}
this.on(eventName, listener.bind(this.model));
}.bind(this));
}
Repository.prototype = Object.create(EventEmitter.prototype);
Object.assign(Repository.prototype, {
// -----------------------------------------------------------------------------
// --SUBSECTION-- Adding Entries
// -----------------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_save
// //////////////////////////////////////////////////////////////////////////////
save(model) {
if (!model.forDB) {
model = new this.model(model);
}
this.emit('beforeCreate', model);
model.emit('beforeCreate');
this.emit('beforeSave', model);
model.emit('beforeSave');
var id_and_rev;
if (this.collection.type() === 3) {
id_and_rev = this.collection.save(model.get('_from'), model.get('_to'), model.forDB());
} else {
id_and_rev = this.collection.save(model.forDB());
}
model.set(id_and_rev);
this.emit('afterSave', model);
model.emit('afterSave');
this.emit('afterCreate', model);
model.emit('afterCreate');
return model;
},
// -----------------------------------------------------------------------------
// --SUBSECTION-- Finding Entries
// -----------------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_byId
// //////////////////////////////////////////////////////////////////////////////
byId(id) {
var data = this.collection.document(id);
return new this.model(data);
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_byExample
// //////////////////////////////////////////////////////////////////////////////
byExample(example) {
var rawDocuments = this.collection.byExample(example).toArray();
return _.map(rawDocuments, function (rawDocument) {
return new this.model(rawDocument);
}.bind(this));
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_firstExample
// //////////////////////////////////////////////////////////////////////////////
firstExample(example) {
var rawDocument = this.collection.firstExample(example);
return rawDocument ? new this.model(rawDocument) : null;
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_all
// //////////////////////////////////////////////////////////////////////////////
all(options) {
if (!options) {
options = {};
}
var rawDocuments = this.collection.all();
if (options.skip) {
rawDocuments = rawDocuments.skip(options.skip);
}
if (options.limit) {
rawDocuments = rawDocuments.limit(options.limit);
}
return _.map(rawDocuments.toArray(), function (rawDocument) {
return new this.model(rawDocument);
}.bind(this));
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_any
// //////////////////////////////////////////////////////////////////////////////
any() {
var data = this.collection.any();
if (!data) {
return null;
}
return new this.model(data);
},
// -----------------------------------------------------------------------------
// --SUBSECTION-- Removing Entries
// -----------------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_remove
// //////////////////////////////////////////////////////////////////////////////
remove(model) {
this.emit('beforeRemove', model);
model.emit('beforeRemove');
var id = model.get('_id'),
result = this.collection.remove(id);
this.emit('afterRemove', model);
model.emit('afterRemove');
return result;
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_removeById
// //////////////////////////////////////////////////////////////////////////////
removeById(id) {
return this.collection.remove(id);
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_removeByExample
// //////////////////////////////////////////////////////////////////////////////
removeByExample(example) {
return this.collection.removeByExample(example);
},
// -----------------------------------------------------------------------------
// --SUBSECTION-- Replacing Entries
// -----------------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_replace
// //////////////////////////////////////////////////////////////////////////////
replace(model) {
var id = model.get('_id') || model.get('_key'),
data = model.forDB(),
id_and_rev = this.collection.replace(id, data);
model.set(id_and_rev);
return model;
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_replaceById
// //////////////////////////////////////////////////////////////////////////////
replaceById(id, data) {
if (data instanceof Model) {
var id_and_rev = this.collection.replace(id, data.forDB());
data.set(id_and_rev);
return data;
}
return this.collection.replace(id, data);
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_replaceByExample
// //////////////////////////////////////////////////////////////////////////////
replaceByExample(example, data) {
return this.collection.replaceByExample(example, data);
},
// -----------------------------------------------------------------------------
// --SUBSECTION-- Updating Entries
// -----------------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_update
// //////////////////////////////////////////////////////////////////////////////
update(model, data) {
this.emit('beforeUpdate', model, data);
model.emit('beforeUpdate', data);
this.emit('beforeSave', model, data);
model.emit('beforeSave', data);
var id = model.get('_id') || model.get('_key'),
id_and_rev = this.collection.update(id, data);
model.set(data);
model.set(id_and_rev);
this.emit('afterSave', model, data);
model.emit('afterSave', data);
this.emit('afterUpdate', model, data);
model.emit('afterUpdate', data);
return model;
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_updateById
// //////////////////////////////////////////////////////////////////////////////
updateById(id, data) {
if (data instanceof Model) {
var id_and_rev = this.collection.update(id, data.forDB());
data.set(id_and_rev);
return data;
}
return this.collection.update(id, data);
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_updateByExample
// //////////////////////////////////////////////////////////////////////////////
updateByExample(example, data, options) {
return this.collection.updateByExample(example, data, options);
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_exists
// //////////////////////////////////////////////////////////////////////////////
exists(id) {
return this.collection.exists(id);
},
// -----------------------------------------------------------------------------
// --SUBSECTION-- Counting Entries
// -----------------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_count
// //////////////////////////////////////////////////////////////////////////////
count() {
return this.collection.count();
}
});
var indexPrototypes = {
skiplist: {
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_range
// //////////////////////////////////////////////////////////////////////////////
range(attribute, left, right) {
var rawDocuments = this.collection.range(attribute, left, right).toArray();
return _.map(rawDocuments, function (rawDocument) {
return new this.model(rawDocument);
}.bind(this));
}
},
geo: {
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_near
// //////////////////////////////////////////////////////////////////////////////
near(latitude, longitude, options) {
var collection = this.collection,
rawDocuments;
if (!options) {
options = {};
}
if (options.geo) {
collection = collection.geo(options.geo);
}
rawDocuments = collection.near(latitude, longitude);
if (options.distance) {
rawDocuments = rawDocuments.distance();
}
if (options.limit) {
rawDocuments = rawDocuments.limit(options.limit);
}
return _.map(rawDocuments.toArray(), function (rawDocument) {
var model = (new this.model(rawDocument)),
distance;
if (options.distance) {
delete model.attributes._distance;
distance = typeof options.distance === 'string' ? options.distance : 'distance';
model[distance] = rawDocument._distance;
}
return model;
}.bind(this));
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_within
// //////////////////////////////////////////////////////////////////////////////
within(latitude, longitude, radius, options) {
var collection = this.collection,
rawDocuments;
if (!options) {
options = {};
}
if (options.geo) {
collection = collection.geo(options.geo);
}
rawDocuments = collection.within(latitude, longitude, radius);
if (options.distance) {
rawDocuments = rawDocuments.distance();
}
if (options.limit) {
rawDocuments = rawDocuments.limit(options.limit);
}
return _.map(rawDocuments.toArray(), function (rawDocument) {
var model = (new this.model(rawDocument)),
distance;
if (options.distance) {
delete model.attributes._distance;
distance = typeof options.distance === 'string' ? options.distance : 'distance';
model[distance] = rawDocument._distance;
}
return model;
}.bind(this));
}
},
fulltext: {
// //////////////////////////////////////////////////////////////////////////////
// / @brief was docuBlock JSF_foxx_repository_fulltext
// //////////////////////////////////////////////////////////////////////////////
fulltext(attribute, query, options) {
if (!options) {
options = {};
}
var rawDocuments = this.collection.fulltext(attribute, query);
if (options.limit) {
rawDocuments = rawDocuments.limit(options.limit);
}
return _.map(rawDocuments.toArray(), function (rawDocument) {
return new this.model(rawDocument);
}.bind(this));
}
}
};
function addIndexMethods (prototype) {
_.each(prototype.indexes, function (index) {
var protoMethods = indexPrototypes[index.type];
if (!protoMethods) {
return;
}
_.each(protoMethods, function (method, key) {
if (prototype[key] === undefined) {
prototype[key] = method;
}
});
});
}
Repository.extend = function (protoProps, staticProps) {
var constructor = extend.call(this, protoProps, staticProps);
if (constructor.prototype.hasOwnProperty('indexes')) {
addIndexMethods(constructor.prototype);
}
return constructor;
};
exports.Repository = Repository;