2 function makeNode(path) {
3 var node = { path: path };
4 if (path[path.length - 1] === '/') {
6 node.contentType = 'application/json';
11 function applyRecursive(path, cb) {
12 var parts = path.match(/^(.*\/)([^\/]+\/?)$/);
14 var dirname = parts[1];
15 var basename = parts[2];
17 if (cb(dirname, basename) && dirname !== '/') {
18 applyRecursive(dirname, cb);
21 throw new Error('inMemoryStorage encountered invalid path : ' + path);
25 RemoteStorage.InMemoryStorage = function(rs) {
27 RemoteStorage.cachingLayer(this);
28 RemoteStorage.eventHandling(this, 'change', 'conflict');
33 RemoteStorage.InMemoryStorage.prototype = {
35 var node = this._storage[path];
37 return promising().fulfill(200, node.body, node.contentType, node.revision);
39 return promising().fulfill(404);
43 put: function(path, body, contentType, incoming) {
44 var oldNode = this._storage[path];
47 contentType: contentType,
50 this._storage[path] = node;
51 this._addToParent(path);
53 this._recordChange(path, { action: 'PUT' });
56 this._emit('change', {
58 origin: incoming ? 'remote' : 'window',
59 oldValue: oldNode ? oldNode.body : undefined,
62 return promising().fulfill(200);
65 'delete': function(path, incoming) {
66 var oldNode = this._storage[path];
67 delete this._storage[path];
68 this._removeFromParent(path);
70 this._recordChange(path, { action: 'DELETE' });
74 this._emit('change', {
76 origin: incoming ? 'remote' : 'window',
77 oldValue: oldNode.body,
81 return promising().fulfill(200);
84 _addToParent: function(path) {
85 var storage = this._storage;
86 applyRecursive(path, function(dirname, basename) {
87 var node = storage[dirname] || makeNode(dirname);
88 node.body[basename] = true;
89 storage[dirname] = node;
94 _removeFromParent: function(path) {
95 var storage = this._storage;
97 applyRecursive(path, function(dirname, basename) {
98 var node = storage[dirname];
100 delete node.body[basename];
101 if (Object.keys(node.body).length === 0) {
102 delete storage[dirname];
105 self._addToParent(dirname);
111 _recordChange: function(path, attributes) {
112 var change = this._changes[path] || {};
113 for(var key in attributes) {
114 change[key] = attributes[key];
117 this._changes[path] = change;
120 clearChange: function(path) {
121 delete this._changes[path];
122 return promising().fulfill();
125 changesBelow: function(path) {
128 for(var key in this._changes) {
129 if (key.substr(0,l) === path) {
130 changes.push(this._changes[key]);
133 return promising().fulfill(changes);
136 setConflict: function(path, attributes) {
137 var event = this._createConflictEvent(path, attributes);
138 this._recordChange(path, { conflict: attributes });
139 this._emit('conflict', event);
142 setRevision: function(path, revision) {
143 var node = this._storage[path] || makeNode(path);
144 node.revision = revision;
145 this._storage[path] = node;
146 return promising().fulfill();
149 getRevision: function(path) {
151 if (this._storage[path]) {
152 rev = this._storage[path].revision;
154 return promising().fulfill(rev);
157 fireInitial: function() {
158 // fireInital fires a change event for each item in the store
159 // inMemoryStorage is always empty on pageLoad
163 RemoteStorage.InMemoryStorage._rs_init = function() {};
165 RemoteStorage.InMemoryStorage._rs_supported = function() {
169 RemoteStorage.InMemoryStorage._rs_cleanup = function() {};
170 })(typeof(window) !== 'undefined' ? window : global);