1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 1× 1× 72× 72× 8× 8× 16× 8× 64× 32× 32× 48× 32× 32× 8× 8× 8× 24× 8× 18× 10× 10× 10× 10× 10× 8× 8× 2× 2× | import Ember from 'ember'; import buildDeepEqual from '../../util/deep-equal'; const deepEqual = buildDeepEqual({ allowEmberObjects: false }); const { merge, typeOf, RSVP: { reject } } = Ember; export default Ember.Object.extend({ database: null, _stringify(arg) { let type = typeOf(arg); if(type === 'array') { let ret = []; for(let i = 0; i < arg.length; i++) { ret.push(this._stringify(arg[i])); } return ret; } else if(type === 'object') { let ret = {}; for(let key in arg) { ret[key] = this._stringify(arg[key]); } return ret; } else if(type === 'function') { let string = arg.toString(); // es6 transpiler adds function name, CouchDB doesn't like it string = string.replace(/(function) ([\w]+)/g, '$1'); return string; } return arg; }, _build(name, hash) { return merge({ _id: this.id(name), language: 'javascript' }, this._stringify(hash)); }, _deepEqual(a, b) { return deepEqual(a, b); }, id(name) { return `_design/${name}`; }, load(name, opts) { opts = merge({ optional: false }, opts); let id = this.id(name); return this.get('database').load(id, { encoded: true }).then((doc) => { return doc; }, (err) => { Iif(opts.optional && err.status === 404) { return; } return reject(err); }); }, save(name, hash) { let doc = this._build(name, hash); return this.load(name, { encoded: true, optional: true }).then((cur) => { if(cur) { doc._rev = cur._rev; if(this._deepEqual(doc, cur)) { return { ok: true, id: doc._id, rev: doc._rev, saved: false }; } } return this.get('database').save(doc, { encoded: true }).then((data) => { data.saved = true; return data; }); }); }, delete(name, opts) { opts = merge({ optional: false }, opts); return this.load(name, { optional: opts.optional }).then((cur) => { if(cur) { return this.get('database').delete(cur._id, cur._rev, { encoded: true }).then((data) => { data.deleted = true; return data; }); } return { ok: true, id: this.id(name), deleted: false }; }); }, }); |