forked from Cormant-Incorporated/backbone-storage-sync
-
Notifications
You must be signed in to change notification settings - Fork 0
/
backbone-storage-sync.js
151 lines (120 loc) · 4.97 KB
/
backbone-storage-sync.js
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define(['backbone', 'lodash'], factory);
}
else if (typeof exports !== 'undefined') {
module.exports = exports = factory(require('backbone'), require('lodash'));
}
else {
factory(Backbone, _);
}
})(function (Backbone, _) {
'use strict';
var syncMethods = {
// Writes current instance data to object store.
create: function (instance, options, deferred) {
if (instance instanceof Backbone.Model) {
// Set the instance `idAttribute` to the `syncKey` so that `isNew()` behaves as expected.
instance.set(instance.idAttribute, _.result(this, 'syncKey'));
}
var json = instance.toJSON(options);
var data = JSON.stringify(json);
this._syncSet(data);
options.success.call(options.context, json);
deferred.resolve(json);
},
// Returns the parsed JSON of the object store.
read: function (instance, options, deferred) {
var data = this._syncGet();
if (!data) {
// Can't parse empty value as json.
options.error.call(options.context, json);
deferred.reject(data);
return;
}
var json = JSON.parse(data);
options.success.call(options.context, json);
deferred.resolve(json);
},
// Overwrites object store with current instance data.
update: function (instance, options, deferred) {
var defaultStr = instance instanceof Backbone.Model ? JSON.stringify({}) : JSON.stringify([]),
storedData = this._syncGet() || defaultStr,
json = instance.toJSON(options);
var data = JSON.stringify(json);
this._syncSet(data);
options.success.call(options.context, json);
deferred.resolve(json);
},
// Merges object store with current instance data.
patch: function (instance, options, deferred) {
var defaultStr = instance instanceof Backbone.Model ? JSON.stringify({}) : JSON.stringify([]),
storedData = this._syncGet() || defaultStr,
json = _.merge(JSON.parse(storedData), instance.toJSON(options));
var data = JSON.stringify(json);
this._syncSet(data);
options.success.call(options.context, json);
deferred.resolve(json);
},
// Removes data from the object store.
delete: function (instance, options, deferred) {
var dataExists = this._syncGet(),
json;// `json` is left `undefined` because the data is deleted from the object store.
if (dataExists) {
this._syncSet(undefined);
instance.unset(instance.idAttribute);
options.success.call(options.context, json);
deferred.resolve(json);
}
else {
options.error.call(options.context, json);
deferred.reject(json);
}
}
};
return {
// Backbone Overrides
// ------------------
// Synchronizes this Backbone model or collection with `syncStore`.
sync: function (method, instance, options) {
var syncMethod = syncMethods[method];
if (!syncMethod) {
throw(new ReferenceError('"method" must be defined'));
}
instance = instance || this;
options = options || {};
_.defaults(options, {
success: _.noop,
error: _.noop,
context: instance,
parse: true
});
if (!this.syncKey) {
throw(new ReferenceError('"syncKey" must be defined'));
}
if (!this.syncStore) {
throw(new ReferenceError('"syncStore" must be defined'));
}
var deferred = Backbone.$.Deferred();
// Defer sync'ing to emulate default sync behavior.
_.defer(syncMethod.bind(this, instance, options, deferred));
instance.trigger('request', instance, deferred, options);
return deferred;
},
// Private Methods
// ---------------
// Returns the value of the object store as unparsed JSON.
_syncGet: function () {
var syncKey = _.result(this, 'syncKey');
var syncStore = _.result(this, 'syncStore');
return syncStore[syncKey];
},
// Sets the object store to `value` (which should be stringified JSON).
_syncSet: function (value) {
var syncKey = _.result(this, 'syncKey');
var syncStore = _.result(this, 'syncStore');
syncStore[syncKey] = value;
}
};
});