@rest-api/react-models
Version:
[](https://www.npmjs.com/package/@rest-api/react-models) [](https://codecov.io/gh/hector7/rest-
139 lines (138 loc) • 6.88 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("../..");
const index_1 = require("./index");
const utils_1 = require("../reducers/utils");
class ComplexSearchActions {
constructor(restModel, url) {
this.actions = {
request: (opts, queryString) => index_1.restActions.request(this.restModel.model.name, this.getUri(opts, { queryString })),
failed: (opts, queryString, error) => index_1.restActions.failed(this.restModel.model.name, this.getUri(opts, { queryString }), error),
invalidate: (opts, queryString) => index_1.restActions.invalidate(this.restModel.model.name, this.getUri(opts, { queryString })),
receive: (opts, queryString, data) => index_1.restActions.receive(this.restModel._id, this.restModel.model.name, this.getUri(opts, { queryString }), this.restModel.getItems(data), this.restModel.getMetaData(data))
};
this.queue = {};
this.restModel = restModel;
this.url = url;
}
getUri(opts, options = {}) {
if (options.id) {
return this.restModel.trailingSlash ? `${this.url(opts)}/${options.id}/` : `${this.url(opts)}/${options.id}`;
}
if (options.queryString) {
const queryString = options.queryString && options.queryString.startsWith('?') ? options.queryString.slice(1) : options.queryString;
return this.restModel.trailingSlash ? `${this.url(opts)}/?${queryString}` : `${this.url(opts)}?${queryString}`;
}
return this.restModel.trailingSlash ? `${this.url(opts)}/` : this.url(opts);
}
get(opts, queryString, callback) {
const actions = this.actions;
return (dispatch, getState) => {
const uri = this.getUri(opts, { queryString });
if (callback)
this.queue[uri].push(callback);
dispatch(this.actions.request(opts, queryString));
const xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = () => {
if (xhttp.readyState === 4 && (xhttp.status === 200 || xhttp.status === 201)) {
const res = JSON.parse(xhttp.responseText);
// add array validation to schema.
if (this.restModel.validateFetch(res)) {
const state = getState();
dispatch(this.actions.receive(opts, queryString, res));
try {
let cb;
const response = {
items: this.restModel.getItems(res)
.map(r => this.restModel.model.schema._useUpdatedSteps(state, r)),
metadata: this.restModel.getMetaData(res)
};
while ((cb = this.queue[uri].shift()) !== undefined) {
cb(null, response);
}
}
catch (err) {
const error = new __1.HttpError(500, err.message);
dispatch(this.actions.failed(opts, queryString, error));
let cb;
while ((cb = this.queue[uri].shift()) !== undefined) {
cb(error);
}
}
}
else {
console.error(JSON.stringify(this.restModel.model.schema.getValidateArrayError(res), null, 2));
throw (new Error(`Response text from "${this.getUri(opts, { queryString })}" is not valid (Schema definition is invalid or bad implementation).
Check console for details.`));
}
}
else if (xhttp.readyState === 4) {
if (index_1.IGNORED_STATUS.indexOf(xhttp.status) > -1) {
return dispatch(this.get(opts, queryString, callback));
}
const error = new __1.HttpError(xhttp.status, xhttp.responseText);
dispatch(this.actions.failed(opts, queryString, error));
let cb;
while ((cb = this.queue[uri].shift()) !== undefined) {
cb(error);
}
}
};
xhttp.open('GET', this.getUri(opts, { queryString }), true);
Object.keys(this.restModel.headers).forEach(key => {
xhttp.setRequestHeader(key, this.restModel.headers[key]);
});
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send();
};
}
fetchIfNeeded(opts, queryString = '', callback) {
const actions = this.actions;
return (dispatch, getState) => {
const uri = this.getUri(opts, { queryString });
if (!this.queue.hasOwnProperty(uri))
this.queue[uri] = [];
const reducer = getState()[this.restModel.model.name];
const req = utils_1.getGeneralRequest(reducer, uri);
if (index_1.shouldFetch(req)) {
return dispatch(this.get(opts, queryString, callback));
}
const promiseCb = (err, res) => {
if (err) {
if (callback)
callback(err);
return;
}
if (callback)
callback(null, res);
};
if (utils_1.isFetching(req)) {
this.queue[uri].push(promiseCb);
}
else {
const error = utils_1.getError(req);
if (error)
return promiseCb(error);
promiseCb(null, {
items: utils_1.getItems(reducer, this.restModel._id, uri),
metadata: utils_1.getMetadata(reducer, uri)
});
}
};
}
//TODO Opts needs to be changed by get key from schema. Won't populate submodels with opts.
fetchPopulatedIfNeeded(opts, queryString = '') {
return (dispatch, getState) => {
const uri = this.getUri(opts, { queryString });
dispatch(this.fetchIfNeeded(opts, queryString));
utils_1.getItems(getState()[this.restModel.model.name], this.restModel._id, uri)
.forEach(i => this.restModel.model.schema._getModelValuesToPopulate(i, (model, id) => {
dispatch(model._actions.fetchByIdPopulatedIfNeeded(id));
}));
};
}
invalidate(opts, queryString = '') {
return this.actions.invalidate(opts, queryString);
}
}
exports.default = ComplexSearchActions;