1 | "use strict";
|
2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6 | return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7 | };
|
8 | var __metadata = (this && this.__metadata) || function (k, v) {
|
9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
10 | };
|
11 | var __param = (this && this.__param) || function (paramIndex, decorator) {
|
12 | return function (target, key) { decorator(target, key, paramIndex); }
|
13 | };
|
14 | var core_1 = require('@angular/core');
|
15 | var http_1 = require('@angular/http');
|
16 | var Observable_1 = require('rxjs/Observable');
|
17 | require('rxjs/add/operator/delay');
|
18 | var http_status_codes_1 = require('./http-status-codes');
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | exports.SEED_DATA = new core_1.OpaqueToken('seedData');
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | var InMemoryBackendConfig = (function () {
|
30 | function InMemoryBackendConfig(config) {
|
31 | if (config === void 0) { config = {}; }
|
32 | Object.assign(this, {
|
33 | defaultResponseOptions: new http_1.BaseResponseOptions(),
|
34 | delay: 500,
|
35 | delete404: false
|
36 | }, config);
|
37 | }
|
38 | return InMemoryBackendConfig;
|
39 | }());
|
40 | exports.InMemoryBackendConfig = InMemoryBackendConfig;
|
41 | exports.isSuccess = function (status) { return (status >= 200 && status < 300); };
|
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 | var InMemoryBackendService = (function () {
|
72 | function InMemoryBackendService(seedData, config) {
|
73 | this.seedData = seedData;
|
74 | this.config = new InMemoryBackendConfig();
|
75 | this.resetDb();
|
76 | var loc = this.getLocation('./');
|
77 | this.config.host = loc.host;
|
78 | this.config.rootPath = loc.pathname;
|
79 | Object.assign(this.config, config);
|
80 | }
|
81 | InMemoryBackendService.prototype.createConnection = function (req) {
|
82 | var res = this.handleRequest(req);
|
83 | var response = new Observable_1.Observable(function (responseObserver) {
|
84 | if (exports.isSuccess(res.status)) {
|
85 | responseObserver.next(res);
|
86 | responseObserver.complete();
|
87 | }
|
88 | else {
|
89 | responseObserver.error(res);
|
90 | }
|
91 | return function () { };
|
92 | });
|
93 | response = response.delay(this.config.delay || 500);
|
94 | return {
|
95 | readyState: http_1.ReadyState.Done,
|
96 | request: req,
|
97 | response: response
|
98 | };
|
99 | };
|
100 |
|
101 | |
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | InMemoryBackendService.prototype.handleRequest = function (req) {
|
116 | var _a = this.parseUrl(req.url), base = _a.base, collectionName = _a.collectionName, id = _a.id, resourceUrl = _a.resourceUrl, query = _a.query;
|
117 | var collection = this.db[collectionName];
|
118 | var reqInfo = {
|
119 | req: req,
|
120 | base: base,
|
121 | collection: collection,
|
122 | collectionName: collectionName,
|
123 | headers: new http_1.Headers({ 'Content-Type': 'application/json' }),
|
124 | id: this.parseId(collection, id),
|
125 | query: query,
|
126 | resourceUrl: resourceUrl
|
127 | };
|
128 | var options;
|
129 | try {
|
130 | if ('commands' === reqInfo.base.toLowerCase()) {
|
131 | options = this.commands(reqInfo);
|
132 | }
|
133 | else if (reqInfo.collection) {
|
134 | switch (req.method) {
|
135 | case http_1.RequestMethod.Get:
|
136 | options = this.get(reqInfo);
|
137 | break;
|
138 | case http_1.RequestMethod.Post:
|
139 | options = this.post(reqInfo);
|
140 | break;
|
141 | case http_1.RequestMethod.Put:
|
142 | options = this.put(reqInfo);
|
143 | break;
|
144 | case http_1.RequestMethod.Delete:
|
145 | options = this.delete(reqInfo);
|
146 | break;
|
147 | default:
|
148 | options = this.createErrorResponse(http_status_codes_1.STATUS.METHOD_NOT_ALLOWED, 'Method not allowed');
|
149 | break;
|
150 | }
|
151 | }
|
152 | else {
|
153 | options = this.createErrorResponse(http_status_codes_1.STATUS.NOT_FOUND, "Collection '" + collectionName + "' not found");
|
154 | }
|
155 | }
|
156 | catch (error) {
|
157 | var err = error.message || error;
|
158 | options = this.createErrorResponse(http_status_codes_1.STATUS.INTERNAL_SERVER_ERROR, "" + err);
|
159 | }
|
160 | options = this.setStatusText(options);
|
161 | if (this.config.defaultResponseOptions) {
|
162 | options = this.config.defaultResponseOptions.merge(options);
|
163 | }
|
164 | return new http_1.Response(options);
|
165 | };
|
166 | |
167 |
|
168 |
|
169 |
|
170 |
|
171 | InMemoryBackendService.prototype.applyQuery = function (collection, query) {
|
172 |
|
173 | var conditions = [];
|
174 | query.paramsMap.forEach(function (value, name) {
|
175 | value.forEach(function (v) { return conditions.push({ name: name, rx: new RegExp(decodeURI(v), 'i') }); });
|
176 | });
|
177 | var len = conditions.length;
|
178 | if (!len) {
|
179 | return collection;
|
180 | }
|
181 |
|
182 | return collection.filter(function (row) {
|
183 | var ok = true;
|
184 | var i = len;
|
185 | while (ok && i) {
|
186 | i -= 1;
|
187 | var cond = conditions[i];
|
188 | ok = cond.rx.test(row[cond.name]);
|
189 | }
|
190 | return ok;
|
191 | });
|
192 | };
|
193 | InMemoryBackendService.prototype.clone = function (data) {
|
194 | return JSON.parse(JSON.stringify(data));
|
195 | };
|
196 | |
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 | InMemoryBackendService.prototype.commands = function (reqInfo) {
|
209 | var command = reqInfo.collectionName.toLowerCase();
|
210 | var method = reqInfo.req.method;
|
211 | var options;
|
212 | switch (command) {
|
213 | case 'resetdb':
|
214 | this.resetDb();
|
215 | options = new http_1.ResponseOptions({ status: http_status_codes_1.STATUS.OK });
|
216 | break;
|
217 | case 'config':
|
218 | if (method === http_1.RequestMethod.Get) {
|
219 | options = new http_1.ResponseOptions({
|
220 | body: this.clone(this.config),
|
221 | status: http_status_codes_1.STATUS.OK
|
222 | });
|
223 | }
|
224 | else {
|
225 |
|
226 | var body = JSON.parse(reqInfo.req.text() || '{}');
|
227 | Object.assign(this.config, body);
|
228 | options = new http_1.ResponseOptions({ status: http_status_codes_1.STATUS.NO_CONTENT });
|
229 | }
|
230 | break;
|
231 | default:
|
232 | options = this.createErrorResponse(http_status_codes_1.STATUS.INTERNAL_SERVER_ERROR, "Unknown command \"" + command + "\"");
|
233 | }
|
234 | return options;
|
235 | };
|
236 | InMemoryBackendService.prototype.createErrorResponse = function (status, message) {
|
237 | return new http_1.ResponseOptions({
|
238 | body: { 'error': "" + message },
|
239 | headers: new http_1.Headers({ 'Content-Type': 'application/json' }),
|
240 | status: status
|
241 | });
|
242 | };
|
243 | InMemoryBackendService.prototype.delete = function (_a) {
|
244 | var id = _a.id, collection = _a.collection, collectionName = _a.collectionName, headers = _a.headers;
|
245 | if (!id) {
|
246 | return this.createErrorResponse(http_status_codes_1.STATUS.NOT_FOUND, "Missing \"" + collectionName + "\" id");
|
247 | }
|
248 | var exists = this.removeById(collection, id);
|
249 | return new http_1.ResponseOptions({
|
250 | headers: headers,
|
251 | status: (exists || !this.config.delete404) ? http_status_codes_1.STATUS.NO_CONTENT : http_status_codes_1.STATUS.NOT_FOUND
|
252 | });
|
253 | };
|
254 | InMemoryBackendService.prototype.findById = function (collection, id) {
|
255 | return collection.find(function (item) { return item.id === id; });
|
256 | };
|
257 | InMemoryBackendService.prototype.genId = function (collection) {
|
258 |
|
259 | var maxId = 0;
|
260 | collection.reduce(function (prev, item) {
|
261 | maxId = Math.max(maxId, typeof item.id === 'number' ? item.id : maxId);
|
262 | }, null);
|
263 | return maxId + 1;
|
264 | };
|
265 | InMemoryBackendService.prototype.get = function (_a) {
|
266 | var id = _a.id, query = _a.query, collection = _a.collection, collectionName = _a.collectionName, headers = _a.headers;
|
267 | var data = collection;
|
268 | if (id) {
|
269 | data = this.findById(collection, id);
|
270 | }
|
271 | else if (query) {
|
272 | data = this.applyQuery(collection, query);
|
273 | }
|
274 | if (!data) {
|
275 | return this.createErrorResponse(http_status_codes_1.STATUS.NOT_FOUND, "'" + collectionName + "' with id='" + id + "' not found");
|
276 | }
|
277 | return new http_1.ResponseOptions({
|
278 | body: { data: this.clone(data) },
|
279 | headers: headers,
|
280 | status: http_status_codes_1.STATUS.OK
|
281 | });
|
282 | };
|
283 | InMemoryBackendService.prototype.getLocation = function (href) {
|
284 | var l = document.createElement('a');
|
285 | l.href = href;
|
286 | return l;
|
287 | };
|
288 | ;
|
289 | InMemoryBackendService.prototype.indexOf = function (collection, id) {
|
290 | return collection.findIndex(function (item) { return item.id === id; });
|
291 | };
|
292 |
|
293 |
|
294 | InMemoryBackendService.prototype.parseId = function (collection, id) {
|
295 | if (!id) {
|
296 | return null;
|
297 | }
|
298 | var isNumberId = collection[0] && typeof collection[0].id === 'number';
|
299 | if (isNumberId) {
|
300 | var idNum = parseFloat(id);
|
301 | return isNaN(idNum) ? id : idNum;
|
302 | }
|
303 | return id;
|
304 | };
|
305 | InMemoryBackendService.prototype.parseUrl = function (url) {
|
306 | try {
|
307 | var loc = this.getLocation(url);
|
308 | var drop = this.config.rootPath.length;
|
309 | var urlRoot = '';
|
310 | if (loc.host !== this.config.host) {
|
311 |
|
312 |
|
313 | drop = 1;
|
314 | urlRoot = loc.protocol + '//' + loc.host + '/';
|
315 | }
|
316 | var path = loc.pathname.substring(drop);
|
317 | var _a = path.split('/'), base = _a[0], collectionName = _a[1], id = _a[2];
|
318 | var resourceUrl = urlRoot + base + '/' + collectionName + '/';
|
319 | collectionName = collectionName.split('.')[0];
|
320 | var query = loc.search && new http_1.URLSearchParams(loc.search.substr(1));
|
321 | return { base: base, id: id, collectionName: collectionName, resourceUrl: resourceUrl, query: query };
|
322 | }
|
323 | catch (err) {
|
324 | var msg = "unable to parse url '" + url + "'; original error: " + err.message;
|
325 | throw new Error(msg);
|
326 | }
|
327 | };
|
328 | InMemoryBackendService.prototype.post = function (_a) {
|
329 | var collection = _a.collection, headers = _a.headers, id = _a.id, req = _a.req, resourceUrl = _a.resourceUrl;
|
330 | var item = JSON.parse(req.text());
|
331 | if (!item.id) {
|
332 | item.id = id || this.genId(collection);
|
333 | }
|
334 |
|
335 |
|
336 | id = item.id;
|
337 | var existingIx = this.indexOf(collection, id);
|
338 | if (existingIx > -1) {
|
339 | collection[existingIx] = item;
|
340 | return new http_1.ResponseOptions({
|
341 | headers: headers,
|
342 | status: http_status_codes_1.STATUS.NO_CONTENT
|
343 | });
|
344 | }
|
345 | else {
|
346 | collection.push(item);
|
347 | headers.set('Location', resourceUrl + '/' + id);
|
348 | return new http_1.ResponseOptions({
|
349 | headers: headers,
|
350 | body: { data: this.clone(item) },
|
351 | status: http_status_codes_1.STATUS.CREATED
|
352 | });
|
353 | }
|
354 | };
|
355 | InMemoryBackendService.prototype.put = function (_a) {
|
356 | var id = _a.id, collection = _a.collection, collectionName = _a.collectionName, headers = _a.headers, req = _a.req;
|
357 | var item = JSON.parse(req.text());
|
358 | if (!id) {
|
359 | return this.createErrorResponse(http_status_codes_1.STATUS.NOT_FOUND, "Missing '" + collectionName + "' id");
|
360 | }
|
361 | if (id !== item.id) {
|
362 | return this.createErrorResponse(http_status_codes_1.STATUS.BAD_REQUEST, "\"" + collectionName + "\" id does not match item.id");
|
363 | }
|
364 | var existingIx = this.indexOf(collection, id);
|
365 | if (existingIx > -1) {
|
366 | collection[existingIx] = item;
|
367 | return new http_1.ResponseOptions({
|
368 | headers: headers,
|
369 | status: http_status_codes_1.STATUS.NO_CONTENT
|
370 | });
|
371 | }
|
372 | else {
|
373 | collection.push(item);
|
374 | return new http_1.ResponseOptions({
|
375 | body: { data: this.clone(item) },
|
376 | headers: headers,
|
377 | status: http_status_codes_1.STATUS.CREATED
|
378 | });
|
379 | }
|
380 | };
|
381 | InMemoryBackendService.prototype.removeById = function (collection, id) {
|
382 | var ix = this.indexOf(collection, id);
|
383 | if (ix > -1) {
|
384 | collection.splice(ix, 1);
|
385 | return true;
|
386 | }
|
387 | return false;
|
388 | };
|
389 | |
390 |
|
391 |
|
392 | InMemoryBackendService.prototype.resetDb = function () {
|
393 | this.db = this.seedData.createDb();
|
394 | };
|
395 | InMemoryBackendService.prototype.setStatusText = function (options) {
|
396 | try {
|
397 | var statusCode = http_status_codes_1.STATUS_CODE_INFO[options.status];
|
398 | options['statusText'] = statusCode ? statusCode.text : 'Unknown Status';
|
399 | return options;
|
400 | }
|
401 | catch (err) {
|
402 | return new http_1.ResponseOptions({
|
403 | status: http_status_codes_1.STATUS.INTERNAL_SERVER_ERROR,
|
404 | statusText: 'Invalid Server Operation'
|
405 | });
|
406 | }
|
407 | };
|
408 | InMemoryBackendService = __decorate([
|
409 | __param(0, core_1.Inject(exports.SEED_DATA)),
|
410 | __param(1, core_1.Inject(InMemoryBackendConfig)),
|
411 | __param(1, core_1.Optional()),
|
412 | __metadata('design:paramtypes', [Object, Object])
|
413 | ], InMemoryBackendService);
|
414 | return InMemoryBackendService;
|
415 | }());
|
416 | exports.InMemoryBackendService = InMemoryBackendService;
|
417 |
|
\ | No newline at end of file |