@crnk/angular-ngrx
Version:
Angular helper library for ngrx-json-api and crnk:
224 lines • 10 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import * as _ from 'lodash';
import { Injectable, Injector } from '@angular/core';
import { Action, Store } from '@ngrx/store';
import { Actions, Effect } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/concatAll';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/mapTo';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/switchMapTo';
import 'rxjs/add/operator/take';
import 'rxjs/add/operator/toArray';
import 'rxjs/add/operator/withLatestFrom';
import { Headers, Http, Request, RequestMethod, RequestOptions } from '@angular/http';
import { ApiApplyInitAction, Document, getNgrxJsonApiZone, NgrxJsonApiActionTypes, NgrxJsonApiService, NgrxJsonApiStore, Query, Resource, ResourceError, StoreResource } from 'ngrx-json-api';
import { ApiApplyFailAction, ApiApplySuccessAction, ApiDeleteFailAction, ApiDeleteSuccessAction, ApiPatchFailAction, ApiPatchSuccessAction, ApiPostFailAction, ApiPostSuccessAction, } from 'ngrx-json-api/src/actions';
import { getPendingChanges } from 'ngrx-json-api/src/utils';
import { NgrxJsonApi } from 'ngrx-json-api/src/api';
var OperationsEffects = /** @class */ (function () {
function OperationsEffects(actions$, store, http, ngrxJsonApi) {
var _this = this;
this.actions$ = actions$;
this.store = store;
this.http = http;
this.ngrxJsonApi = ngrxJsonApi;
this.headers = new Headers({
'Content-Type': 'application/json-patch+json',
'Accept': 'application/json-patch+json'
});
this.applyResources$ = this.actions$
.ofType(NgrxJsonApiActionTypes.API_APPLY_INIT)
.withLatestFrom(this.store, function (action, state) {
var initAction = action;
var zoneId = initAction.zoneId;
var ngrxstore = getNgrxJsonApiZone(state, zoneId);
var payload = initAction.payload;
var pending = getPendingChanges(ngrxstore.data, payload.ids, payload.include, false);
if (pending.length === 0) {
return Observable.of(new ApiApplySuccessAction([], zoneId));
}
var operations = [];
for (var _i = 0, pending_1 = pending; _i < pending_1.length; _i++) {
var pendingChange = pending_1[_i];
operations.push(_this.toOperation(pendingChange));
}
var requestOptions = new RequestOptions({
method: RequestMethod.Patch,
url: _this.ngrxJsonApi['config']['apiUrl'] + '/operations/',
body: JSON.stringify(operations)
});
var request = new Request(requestOptions.merge({
headers: _this.headers
}));
return _this.http.request(request)
.map(function (res) { return res.json(); })
.map(function (operationResponses) {
if (!_.isArray(operationResponses)) {
throw new Error('expected array as operations response');
}
var actions = [];
for (var _i = 0, _a = Object.keys(operationResponses); _i < _a.length; _i++) {
var index = _a[_i];
var operationResponse = operationResponses[index];
var pendingChange = pending[index];
actions.push(_this.toResponseAction(pendingChange, operationResponse, zoneId));
}
return _this.toApplyAction(actions, zoneId);
})
.catch(function (errorResponse) {
// transform http to json api error
var error = {
status: errorResponse.status.toString(),
code: errorResponse.statusText
};
var errors = [error];
var actions = [];
for (var _i = 0, pending_2 = pending; _i < pending_2.length; _i++) {
var pendingChange = pending_2[_i];
var operationResponse = {
errors: errors,
status: 500
};
actions.push(_this.toResponseAction(pendingChange, operationResponse, zoneId));
}
return Observable.of(new ApiApplyFailAction(actions, zoneId));
});
})
.flatMap(function (actions) { return actions; });
// disable default implementation
this.ngrxJsonApi['config']['applyEnabled'] = false;
}
OperationsEffects.prototype.toOperation = function (pendingChange) {
if (pendingChange.state === 'CREATED') {
return {
op: 'POST',
path: pendingChange.type,
value: {
id: pendingChange.hasTemporaryId ? undefined : pendingChange.id,
type: pendingChange.type,
attributes: pendingChange.attributes,
relationships: pendingChange.relationships
}
};
}
else if (pendingChange.state === 'UPDATED') {
return {
op: 'PATCH',
path: pendingChange.type + '/' + pendingChange.id,
value: {
id: pendingChange.id,
type: pendingChange.type,
attributes: pendingChange.attributes,
relationships: pendingChange.relationships
}
};
}
else if (pendingChange.state === 'DELETED') {
return {
op: 'DELETE',
path: pendingChange.type + '/' + pendingChange.id
};
}
else {
throw new Error('unknown state ' + pendingChange.state);
}
};
OperationsEffects.prototype.toApplyAction = function (actions, zoneId) {
for (var _i = 0, actions_1 = actions; _i < actions_1.length; _i++) {
var action = actions_1[_i];
if (action.type === NgrxJsonApiActionTypes.API_POST_FAIL
|| action.type === NgrxJsonApiActionTypes.API_PATCH_FAIL
|| action.type === NgrxJsonApiActionTypes.API_DELETE_FAIL) {
return new ApiApplyFailAction(actions, zoneId);
}
}
return new ApiApplySuccessAction(actions, zoneId);
};
OperationsEffects.prototype.toResponseAction = function (pendingChange, operationResponse, zoneId) {
var success = operationResponse.status >= 200 && operationResponse.status < 300;
var jsonApiData = _.omit(operationResponse, ['status']);
var query = {
type: pendingChange.type,
id: pendingChange.id
};
if (pendingChange.state === 'CREATED') {
if (success) {
// get generated primary key
query.id = jsonApiData.data['id'];
if (!query.id) {
throw new Error('id not returned for operation');
}
return new ApiPostSuccessAction({
jsonApiData: jsonApiData,
query: query
}, zoneId);
}
else {
return new ApiPostFailAction({
jsonApiData: jsonApiData,
query: query
}, zoneId);
}
}
else if (pendingChange.state === 'UPDATED') {
if (success) {
return new ApiPatchSuccessAction({
jsonApiData: jsonApiData,
query: query
}, zoneId);
}
else {
return new ApiPatchFailAction({
jsonApiData: jsonApiData,
query: query
}, zoneId);
}
}
else if (pendingChange.state === 'DELETED') {
if (success) {
return new ApiDeleteSuccessAction({
query: query
}, zoneId);
}
else {
return new ApiDeleteFailAction({
jsonApiData: jsonApiData,
query: query
}, zoneId);
}
}
else {
throw new Error('unknown state ' + pendingChange.state);
}
};
OperationsEffects.decorators = [
{ type: Injectable },
];
/** @nocollapse */
OperationsEffects.ctorParameters = function () { return [
{ type: Actions, },
{ type: Store, },
{ type: Http, },
{ type: NgrxJsonApiService, },
]; };
__decorate([
Effect(),
__metadata("design:type", Object)
], OperationsEffects.prototype, "applyResources$", void 0);
return OperationsEffects;
}());
export { OperationsEffects };
//# sourceMappingURL=crnk.operations.effects.js.map