1 | var dotty = require('dotty');
|
2 | var clone = require('clone');
|
3 | var xtend = require('xtend');
|
4 |
|
5 | function BaseModel(data, lance, parent, parentPath) {
|
6 | if(!(this instanceof BaseModel)) {
|
7 | return new BaseModel(data);
|
8 | }
|
9 | var self = this;
|
10 | if(typeof data !== 'object') {
|
11 | throw 'nope';
|
12 | }
|
13 | if(!lance) {
|
14 | throw 'nope';
|
15 | }
|
16 | self._lance = lance;
|
17 | self._data = data;
|
18 | self._isDirty = false;
|
19 | self._parent = parent;
|
20 | self._parentPath = parentPath;
|
21 | self._collection = [];
|
22 |
|
23 | self._populateCollection();
|
24 | }
|
25 |
|
26 | var proto = BaseModel.prototype;
|
27 |
|
28 | proto._populateCollection = function() {
|
29 | var self = this;
|
30 | var collectionNode = self.meta('collectionNode');
|
31 | if(!collectionNode) {
|
32 | return;
|
33 | }
|
34 | self._collection = self._data[collectionNode]
|
35 | .map(function(item) {
|
36 | return self._lance.wrap(item, self);
|
37 | });
|
38 | }
|
39 |
|
40 | proto.get = function(field) {
|
41 | var self = this;
|
42 | var out = dotty.get(self._data, field);
|
43 | if(typeof out === 'object' && !Array.isArray(out)) {
|
44 | return self._lance.wrap(out, self);
|
45 | }
|
46 | return out;
|
47 | }
|
48 |
|
49 | proto.set = function(field, value) {
|
50 | var self = this;
|
51 | self._isDirty = true;
|
52 | if(self._parent) {
|
53 | self._parent.set(self._parentPath + '.' + field, value);
|
54 | }
|
55 | return dotty.put(self._data, field, value);
|
56 | }
|
57 |
|
58 | proto.meta = function(field) {
|
59 | var self = this;
|
60 | return self.get('_meta.' + field);
|
61 | }
|
62 |
|
63 | proto.fetch = function(linkName, opts) {
|
64 | var self = this;
|
65 | opts = xtend({}, opts);
|
66 | var uri = dotty.get(self._data, ['_links', linkName, 'href']);
|
67 | if(!uri) {
|
68 | return new Promise(function() {
|
69 | throw new Error('invalid linkName');
|
70 | });
|
71 | }
|
72 | return self._lance.fetchPath(uri, opts);
|
73 | }
|
74 |
|
75 | proto.save = function(opts) {
|
76 | var self = this;
|
77 | opts = xtend({
|
78 | headers: {
|
79 | 'Content-Type': 'application/lance+json'
|
80 | }
|
81 | }, opts);
|
82 | if(!self._isDirty) {
|
83 | return new Promise(function() {
|
84 | return self;
|
85 | });
|
86 | }
|
87 | var link = dotty.get(self._data, '_links.self.href');
|
88 | if(!link) {
|
89 | return new Promise(function() {
|
90 | throw 'not updateable';
|
91 | });
|
92 | }
|
93 | var uri = self._lance._baseUrl + link;
|
94 | return fetch(uri, {
|
95 | method: 'put',
|
96 | headers: opts.headers,
|
97 | body: JSON.stringify(self._data)
|
98 | })
|
99 | .then(function(data) {
|
100 | return data.json();
|
101 | })
|
102 | .then(function(json) {
|
103 | self._isDirty = false;
|
104 | self.setData(json);
|
105 | return self;
|
106 | });
|
107 | }
|
108 |
|
109 | proto.setData = function(data) {
|
110 | var self = this;
|
111 | self._data = data;
|
112 | self._populateCollection();
|
113 | }
|
114 |
|
115 | proto.fetchMore = function(params, opts) {
|
116 | var self = this;
|
117 | return self.fetch('self', params, opts);
|
118 | }
|
119 |
|
120 | proto.delete = function(opts) {
|
121 | var self = this;
|
122 | opts = xtend({
|
123 | headers: {}
|
124 | }, opts);
|
125 | var link = dotty.get(self._data, '_links.self.href');
|
126 | if(!link) {
|
127 | return new Promise(function() {
|
128 | throw new Error('not deletable');
|
129 | })
|
130 | }
|
131 | var uri = self._lance._baseUrl + link;
|
132 | return fetch(uri, {
|
133 | method: 'delete',
|
134 | headers: opts.headers
|
135 | })
|
136 | .then(function(data) {
|
137 | return data.json();
|
138 | })
|
139 | .then(function(json) {
|
140 | return json;
|
141 | });
|
142 | }
|
143 |
|
144 | proto.collection = function() {
|
145 | var self = this;
|
146 | return self._collection;
|
147 | }
|
148 |
|
149 | proto.totalCount = function() {
|
150 | var self = this;
|
151 | var totalCount = dotty.get(self._data, '_meta.totalCount');
|
152 | if(totalCount || totalCount === 0 || totalCount === '0') {
|
153 | return totalCount;
|
154 | } else if(self.isCollection()) {
|
155 | return self.collection().length;
|
156 | } else if(Array.isArray(self._data)) {
|
157 | return self._data.length
|
158 | } else {
|
159 | return 0;
|
160 | }
|
161 | }
|
162 |
|
163 | proto.currentPage = function() {
|
164 | var self = this;
|
165 | if (self.isCollection()) {
|
166 | return dotty.get(self._data, '_meta.currentPage') || 1;
|
167 | } else {
|
168 | return undefined;
|
169 | }
|
170 | }
|
171 |
|
172 | proto.pageCount = function() {
|
173 | var self = this;
|
174 | if (self.isCollection()) {
|
175 | return dotty.get(self._data, '_meta.pageCount') || 1;
|
176 | } else {
|
177 | return undefined;
|
178 | }
|
179 | }
|
180 |
|
181 | proto.nextPage = function() {
|
182 | var self = this;
|
183 | var link = dotty.get(self._data, '_links.next.href');
|
184 | if(!link) {
|
185 | return new Promise(function() {
|
186 | return false;
|
187 | });
|
188 | }
|
189 | var uri = self._lance._baseUrl + link;
|
190 | return fetch(uri)
|
191 | .then(function(data) {
|
192 | return data.json();
|
193 | })
|
194 | .then(function(json) {
|
195 | return self._lance.wrap(json);
|
196 | });
|
197 | }
|
198 |
|
199 | proto.prevPage = function() {
|
200 | var self = this;
|
201 | var link = dotty.get(self._data, '_links.pev.href');
|
202 | if(!link) {
|
203 | return new Promise(function() {
|
204 | return false;
|
205 | });
|
206 | }
|
207 | var uri = self._lance._baseUrl + link;
|
208 | return fetch(uri)
|
209 | .then(function(data) {
|
210 | return data.json();
|
211 | })
|
212 | .then(function(json) {
|
213 | return self._lance.wrap(json);
|
214 | });
|
215 | }
|
216 |
|
217 | proto.isDirty = function() {
|
218 | var self = this;
|
219 | return self._isDirty;
|
220 | }
|
221 |
|
222 | proto.isCollection = function() {
|
223 | var self = this;
|
224 | return (self.meta('collectionNode')) ? true : false;
|
225 | }
|
226 |
|
227 | proto.hasClass = function() {
|
228 | var self = this;
|
229 | return (self.meta('class')) ? true : false;
|
230 | }
|
231 |
|
232 | proto.hasSelf = function() {
|
233 | var self = this;
|
234 | var link = dotty.get(self._data, '_links.self.href');
|
235 | return (link) ? true : false;
|
236 | }
|
237 |
|
238 | proto.forEachLink = function(cb) {
|
239 | var self = this;
|
240 | for (var key in self._data._links) {
|
241 | cb(key, self._data._links[key]);
|
242 | }
|
243 | }
|
244 |
|
245 | proto.forEachMeta = function(cb) {
|
246 | var self = this;
|
247 | for (var key in self._data._meta) {
|
248 | cb(key, self._data._meta[key]);
|
249 | }
|
250 | }
|
251 |
|
252 | proto.forEachGetter = function(cb) {
|
253 | var self = this;
|
254 | for (var key in self._data) {
|
255 | cb(key, self.get(key));
|
256 | }
|
257 | }
|
258 |
|
259 | proto.toJson = function() {
|
260 | var self = this;
|
261 | var _data = clone(self._data);
|
262 | delete _data._meta;
|
263 | delete _data._links;
|
264 | return _data;
|
265 | }
|
266 |
|
267 | proto.toLanceJson = function() {
|
268 | var self = this;
|
269 | var _data = clone(self._data);
|
270 | return _data;
|
271 | }
|
272 |
|
273 | module.exports = BaseModel;
|