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
152
153
154
155
156
157
158
159
160
161
162
163
164
|
var Q = require('q');
/**
* OKResource!
* TODO Would be nicer to compose this with an existing resource
* module, but haven't found a good fit. Should keep an eye on
* 'resource' by bigcompany for an update.
*/
function OKResource(options) {
if (!(this instanceof OKResource)) return new OKResource(options);
options = options || {};
if (!options.type)
throw new Error('No resource type provided to OKResource')
if (!options.schema)
throw new Error('No schema provided to OKResource');
if (!options.db)
throw new Error('No DB provided to OKResource');
var schema = options.schema;
// Iterate through spec to find field which will act as the
// resource id in da db.
var idField = Object.keys(schema.spec).reduce(function(idField, prop) {
var spec = schema.spec[prop];
if (spec.id)
idField = prop;
return idField;
// If schema has a prop called 'id', default to that one
}, schema.id && 'id');
if (!idField)
throw new Error('Bad schema: no ID field');
var type = options.type;
this._db = options.db;
// Define properties which are part of the API
Object.defineProperty(this, 'schema', {
value: schema,
writable: false,
enumerable: true
});
Object.defineProperty(this, 'spec', {
value: schema.spec,
writable: false,
enumerable: true
});
Object.defineProperty(this, 'type', {
value: type,
writable: false,
enumerable: true
});
Object.defineProperty(this, 'idField', {
value: idField,
writable: false,
enumerable: true
});
}
/**
* Throws an error if data does not conform to schema
*/
OKResource.prototype.assertValid = function(data) {
this.schema.assertValid(data);
};
OKResource.prototype.all = function() {
return this._db.getAll(this.type);
};
OKResource.prototype.create = function(data) {
data = data || {};
var id = data[this.idField];
return Q.promise(function(resolve, reject) {
if (!id) {
reject(new Error('Data does not contain ID property'));
} else {
this._db.create(this.type, data).then(resolve, reject);
}
});
};
OKResource.prototype.destroy = function(data) {
data = data || {};
var id = data[this.idField];
return Q.promise(function(resolve, reject) {
if (!id) {
reject(new Error('Data does not contain ID property'));
} else {
this._db.remove(this.type, data.id, data).then(resolve, reject);
}
});
};
OKResource.prototype.find = function(query) {
return Q.promise(function(resolve, reject) {
if (!query) {
throw new Error('No query given');
} else {
this._db.find(this.type, query).then(resolve, reject);
}
});
};
OKResource.prototype.get = function(id) {
var db = this._db;
var type = this.type;
var idField = this.idField;
return Q.promise(function(resolve, reject) {
if (!id) {
throw new Error('No ID given');
} else {
// We have the id, but we still need
// to resolve which field is the id field
// to match
var query = {};
query[idField] = id;
db.get(type, query).then(resolve, reject);
}
});
};
OKResource.prototype.update = function(data) {
data = data || {};
var id = data[this.idField];
var db = this._db;
var type = this.type;
var idField = this.idField;
return Q.promise(function(resolve, reject) {
if (!id) {
reject(new Error('Data does not contain ID property'));
} else {
var query = {};
query[idField] = data[idField];
db.put(type, query, data).then(resolve, reject);;
}
});
};
OKResource.prototype.updateOrCreate = function(data) {
data = data || {};
var id = data[this.idField];
var type = this.type;
var db = this._db;
var idField = this.idField;
return Q.promise(function(resolve, reject) {
if (!id) {
reject(new Error('Cannot updateOrCreate without ID'));
} else {
db.get(type, data.id).then(function(cached) {
var query = {};
query[idField] = id;
if (cached)
db.put(type, query, data).then(resolve, reject);
else
db.create(type, data).then(resolve, reject);
}, reject);
}
});
};
module.exports = OKResource;
|