UNPKG

@rest-api/react-models

Version:

[![npm version](https://img.shields.io/npm/v/@rest-api/react-models)](https://www.npmjs.com/package/@rest-api/react-models) [![codecov](https://codecov.io/gh/hector7/rest-api-react-models/branch/master/graph/badge.svg)](https://codecov.io/gh/hector7/rest-

139 lines (138 loc) 6.88 kB
"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;