| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- 'use strict';
- var JSONStream = require('JSONStream');
- var Promise = require('bluebird');
- var fs = require('graceful-fs');
- var _ = require('lodash');
- var Model = require('./model');
- var Schema = require('./schema');
- var SchemaType = require('./schematype');
- var util = require('./util');
- var WarehouseError = require('./error');
- var pkg = require('../package.json');
- var extend = _.assign;
- /**
- * Database constructor.
- *
- * @class
- * @param {object} [options]
- * @param {number} [options.version=0] Database version
- * @param {string} [options.path] Database path
- * @param {function} [options.onUpgrade] Triggered when the database is upgraded
- * @param {function} [options.onDowngrade] Triggered when the database is downgraded
- */
- function Database(options) {
- this.options = extend({
- version: 0,
- onUpgrade: function() {},
- onDowngrade: function() {}
- }, options);
- this._models = {};
- var _Model = this.Model = function(name, schema) {
- Model.call(this, name, schema);
- };
- util.inherits(_Model, Model);
- _Model.prototype._database = this;
- }
- /**
- * Creates a new model.
- *
- * @param {string} name
- * @param {Schema|object} [schema]
- * @return {Model}
- */
- Database.prototype.model = function(name, schema) {
- if (this._models[name]) {
- return this._models[name];
- }
- var model = this._models[name] = new this.Model(name, schema);
- return model;
- };
- /**
- * Loads database.
- *
- * @param {function} [callback]
- * @return {Promise}
- */
- Database.prototype.load = function(callback) {
- var path = this.options.path;
- var self = this;
- if (!path) throw new WarehouseError('options.path is required');
- return new Promise(function(resolve, reject) {
- var src = fs.createReadStream(path, {encoding: 'utf8'});
- var oldVersion = 0;
- var stream = JSONStream.parse([true, true], function(value, keys) {
- switch (keys.shift()){
- case 'meta':
- if (keys.shift() === 'version') {
- oldVersion = value;
- }
- break;
- case 'models':
- self.model(keys.shift())._import(value);
- break;
- }
- });
- src
- .pipe(stream)
- .on('error', reject)
- .on('end', function() {
- resolve(oldVersion);
- });
- }).then(function(oldVersion) {
- var newVersion = self.options.version;
- if (newVersion > oldVersion) {
- return self.options.onUpgrade(oldVersion, newVersion);
- } else if (newVersion < oldVersion) {
- return self.options.onDowngrade(oldVersion, newVersion);
- }
- }).asCallback(callback);
- };
- /**
- * Saves database.
- *
- * @param {function} [callback]
- * @return {Promise}
- */
- Database.prototype.save = function(callback) {
- var path = this.options.path;
- var self = this;
- if (!path) throw new WarehouseError('options.path is required');
- return new Promise(function(resolve, reject) {
- var stream = fs.createWriteStream(path);
- // Start
- stream.write('{');
- // Meta
- stream.write('"meta":' + JSON.stringify({
- version: self.options.version,
- warehouse: pkg.version
- }) + ',');
- // Export models
- var models = self._models;
- var keys = Object.keys(models);
- var model, key;
- stream.write('"models":{');
- for (var i = 0, len = keys.length; i < len; i++) {
- key = keys[i];
- model = models[key];
- if (!model) continue;
- if (i) stream.write(',');
- stream.write('"' + key + '":' + model._export());
- }
- stream.write('}');
- // End
- stream.end('}');
- stream.on('error', reject)
- .on('finish', resolve);
- }).asCallback(callback);
- };
- Database.Schema = Database.prototype.Schema = Schema;
- Database.SchemaType = Database.prototype.SchemaType = SchemaType;
- Database.version = pkg.version;
- module.exports = Database;
|