Repository URL to install this package:
|
Version:
1.2.13 ▾
|
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Request = void 0;
var _exotic = require("exotic");
var _chainAbleBoost = require("chain-able-boost");
var _queryStringify = require("./deps/queryStringify");
var _config = require("./config");
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const IS_BROWSER = typeof window === 'object';
/**
* @type {Map}
* @alias OneRequest
*/
class Request {
/**
* @description map of middleware we can call on lifecycle hooks
* @typedef {IntersectionObserverCallback}
*
* @note could also be .subscribe() to add, since it's quite observable-like
*
* ...for now though...
*
* @example
* import Request from 'modules/oneRequest'
* function middlewareForLocalStorage(request: Request, eventData: {}): void {}
* Request.middleware.set('name', middlewareForLocalStorage)
*/
constructor() {
Object.defineProperty(this, "onBrowser", {
configurable: true,
enumerable: true,
writable: true,
value: handler => {
// this.store.onBrowser = handler
const onBrowser = (oneRequest, arg) => {
if (IS_BROWSER === false) {
handler(oneRequest, arg);
}
};
this.use(onBrowser);
return this;
}
});
Object.defineProperty(this, "onServer", {
configurable: true,
enumerable: true,
writable: true,
value: handler => {
// this.store.onServer = handler
const onServer = (oneRequest, arg) => {
if (IS_BROWSER === false) {
handler(oneRequest, arg);
}
};
this.use(onServer);
return this;
}
});
Object.defineProperty(this, "onSuccess", {
configurable: true,
enumerable: true,
writable: true,
value: handler => {
return this._set('onSuccess', handler);
}
});
Object.defineProperty(this, "onError", {
configurable: true,
enumerable: true,
writable: true,
value: handler => {
return this._set('onError', handler);
}
});
// store is a standard name for every piece of data being set and get in a class
this.store = {}; // until we fix, set debug always true manually
this.setDebug(true); // default to POST -- 50/1 POST TO GET
// this.setMethod(POST)
// could be done onCreate
const POST = _config.config.get('POST');
this.setMethod(POST);
this.emit('onCreate');
}
/**
* @event lifecycle middleware called for this event
* @param {String} eventName
* @param {Object} [eventData=""]
* @return {Request} @chainable
*/
emit(eventName, eventData = _exotic.EMPTY_OBJ) {
// @todo @perf can use Object.seal
const type = {
type: eventName
};
const arg = eventData === _exotic.EMPTY_OBJ ? type : _objectSpread({}, eventData, type);
const callMiddleware = (middleware, index) => {
// if (isFunction(middleware.when)) / isSatisfied / @todo
middleware(this, arg);
};
Request.middleware.forEach(callMiddleware);
if ((0, _exotic.isArray)(this.middlewareList)) {
this.middlewareList.forEach(callMiddleware);
} // !!!!!!!!!
// this.setParams(defaultParams)
return this;
}
use(middleware) {
this.middlewareList.push(middleware);
return this;
}
/**
* @private
*/
_set(name, value) {
this.store[name] = value;
return this;
}
_get(name) {
return this.store[name];
}
_has(name) {
return !!this.store[name];
}
/**
*
*/
del() {} //
/**
*
*/
get() {} //
/**
* patch, put
*/
post() {} //
/**
*
*/
then() {} //
/**
* ===
*/
type(type) {
this._set('type', type);
} // cert() {}
// key() {}
// json() {}
// xml() {}
// responseType() {}
// auth('tobi', 'learnboost')
// .withCredentials()
// .redirects(2)
// .on('error', handle)
// --- setters
setDebug(shouldDebug = false) {
return this._set('debug', shouldDebug);
}
url(url) {
return this.setUrl(url);
}
setUrl(url) {
return this._set('url', url);
}
/**
* === sadly is ALSO for query ===
* === matters for POST ===
*/
setParams(params) {
return this._set('params', params);
}
params(params) {
return this.setParams(params); // return this._set('params', params)
}
/**
* @tutorial https://github.com/node-nock/nock#specifying-request-query-string
* @param {Object} params
* @return {Request} @chainable
*/
setDefaultParams(params) {
// for now just sets params since we object assign
// return this._set('params', params)
return this.setParams(params); // return this._set('_defaultParams', params)
// return this._set('params', params)
}
/**
* @deprecated - is handled in setData for now
* @TODO
* @description for POST calls
* @param {*} body
*/
setBody(body) {
return this._set('body', body);
}
setData(fixtureData) {
return this._set('data', fixtureData);
}
setFormData(formData) {
return this._set('formData', formData);
}
transformData(fn, data) {
return this._set('data', fn(data));
}
setMethod(method) {
return this._set('method', method);
} // --- helpers
log() {
if (this.store.debug === true) {
console.log.apply(console, arguments);
}
return this;
}
validateRequestStore() {
if (!this._has('url')) {
throw new Error('missing url, use request.setUrl(urlForThisEndpoint)');
}
if (!this._has('data')) {
throw new Error('missing fixture data, use request.setData(fixtureData)');
} // if (!this._has('params')) {
// console.log(
// 'did not pass in params, might want to disable this log because not every request needs params?'
// )
// }
} // PATCH, PUT, REQUEST, AXIOSER
get isPost() {
const methodName = this.store.method.methodName || this.store.methodName;
return methodName === 'POST' || methodName === 'REQUEST' || methodName === 'AXIOSER' || methodName === 'post';
}
get isGet() {
const methodName = this.store.method.methodName || this.store.methodName;
return methodName === 'GET' || methodName === 'get'; // return this.store.method.methodType === 'GET'
}
setMethodType(type) {
console.warn('@deprecated .setMethodType');
return this;
}
/**
* @deprecated
*/
setMethodName(methodName) {
console.warn('@deprecated .setMethodName');
this.store.methodName = name; // The actual string representation of 'post'|'get'
return this._set('methodName', methodName);
}
stringifyParams(paramArg = undefined) {
let params = paramArg || this._get('params');
/**
* HORRIBLE_BAD_SHOULD_BE_FIXED_BY_BACKEND_SHAME
*/
// params.storeId = params.storeid
// @todo @perf
params = (0, _chainAbleBoost.cloneJSON)(params);
params = (0, _queryStringify.stringifyParamsRecursively)(params);
return params;
}
/**
* @event toRequest
* @event ->onRequest
*
* @see https://github.com/mzabriskie/axios
* @return {AsyncFunction} call to get data
*/
toRequest() {
// @todo - add cloning through chaining or scoped props
// @todo add dynamic url
// add a property to not create fn each time
if (this.dynamicRequest) {
return this.dynamicRequest;
}
this.emit('toRequest');
/**
* @note could accept string param as first arg
* @todo could chain set the params or url
*/
// @lint @todo @fixme @split
// eslint-disable-next-line
const dynamicAxiosRequest = async (dynamicParams = undefined, dynamicUrl = undefined) => {
// @NOTE this is how to return mocks
// return this.store.data
let _store = this.store,
url = _store.url,
debug = _store.debug,
method = _store.method,
onError = _store.onError,
onSuccess = _store.onSuccess;
const FETCHREQUEST = _config.config.get('FETCHREQUEST'); // dynamicParams => formBody
// defaultParams/queryParams => string for the end of the url
let queryParams = this.store.params;
let params = queryParams; // merge in dynamic params.. but not everything has params
if (dynamicParams !== undefined) {
// if (params !== undefined) {
// params = Object.assign(params, dynamicParams)
// } else {
// params = Object.assign({}, dynamicParams)
// }
if (params !== undefined) {
params = _objectSpread({}, queryParams, dynamicParams);
} else {
params = _objectSpread({}, dynamicParams);
}
}
const constantParams = _config.config.get('constantParams');
Object.assign(params, constantParams);
Object.assign(queryParams, constantParams);
if (process.env.LOG_REQUEST_PARAMS) {
console.log('_______constantParams', constantParams);
console.log('___MERGED_PARAMS', queryParams);
}
if (dynamicUrl !== undefined) {
url = url + '/' + dynamicUrl;
} // handle the transform
if ((0, _exotic.isObj)(params)) {
params = (0, _queryStringify.stringifyProperties)(params);
} // NOW CHANGED BACK
// if (clientDomain === 'reactdemo.skavaone.com') {
// queryParams.storeId = storeId
// } else {
// queryParams.storeid = storeId
// }
// queryParams.storeId = queryParams.storeid
queryParams = this.stringifyParams(queryParams || _exotic.EMPTY_OBJ); // does it just remove at top level...?
queryParams = decodeURIComponent(queryParams);
/**
* @type {AxiosData}
*/
const axiosData = {
params
/**
* @todo split here ===
*
* @type {Array<Data>}
*/
};
const args = [url, axiosData]; // const ENABLE_FOR_POST = true
if (this.isPost) {
// @todo - should work for every request get and post
url = `${url}?${queryParams}`;
const formData = this.stringifyParams(dynamicParams);
const axiosPostData = {
data: formData
/**
* @type {AxiosRequestConfig}
*/
};
const axiosRequestConfig = {
withCredentials: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
const axioserRequestConfig = _objectSpread({
url,
method: 'post'
}, axiosPostData, axiosRequestConfig);
if (process.env.LOG_REQUEST_PARAMS) {
console.log('[oneRequest] params: ', axioserRequestConfig);
}
const _ref = await FETCHREQUEST.call(this, axioserRequestConfig),
_ref2 = _slicedToArray(_ref, 2),
error = _ref2[0],
response = _ref2[1]; // console.dev({ error, response })
if (process.env.LOG_REQUEST_RESPONSE) {
console.log('[oneRequest] response: ', response);
}
if (error && onError) {
if (process.env.LOG_REQUEST_ERROR) {
console.log('[oneRequest] error: ', error);
} // , response, this
return onError(error) || response.data;
} else if (!error && onSuccess) {
// or .data...
onSuccess(response.data, response);
}
return response.data;
} // =========
if (process.env.LOG_REQUEST_PARAMS) {
console.log('[oneRequest] params: ', args);
}
/**
* @description do our post call
* @see chain/lego/oneRequest
*/
const _ref3 = await method.apply(this, args),
_ref4 = _slicedToArray(_ref3, 2),
error = _ref4[0],
response = _ref4[1];
if (process.env.LOG_REQUEST_RESPONSE) {
console.log('[oneRequest] response: ', response);
}
if (process.env.LOG_REQUEST_ERROR) {
console.log('[oneRequest] error: ', error);
} // if we have an error, for now, log it
if (error) {
// this.log({ error, response, ...this.store })
if (error && onError) {
// , response, this
return onError(error) || response.data;
} else if (!error && onSuccess) {
// or .data...
onSuccess(response.data, response);
return response.data;
} // return onCall(response.data, response) || response.data
return response.data;
} // if (debug) {
// this.log({ error, response, params, ...this.store })
// }
// autofix(response.data)
return response.data;
};
this.dynamicAxiosRequest = dynamicAxiosRequest;
dynamicAxiosRequest.toChain = (0, _chainAbleBoost.always)(this);
dynamicAxiosRequest.onError = this.onError;
dynamicAxiosRequest.onSuccess = this.onSuccess;
return dynamicAxiosRequest;
} // query<T>(options: WatchQueryOptions): Promise<ApolloQueryResult<T>>
// mutate<T>(options: MutationOptions<T>): Promise<FetchResult<T>>
// subscribe(options: SubscriptionOptions): Observable<any>
// readQuery<T>(options: DataProxy.Query): T | null
// readFragment<T>(options: DataProxy.Fragment): T | null
// writeQuery(options: DataProxy.WriteQueryOptions): void
// writeFragment(options: DataProxy.WriteFragmentOptions): void
// gql = {
// // CRUD
// query: 'QueryHere',
// // dynamic
// // variables: {},
// }
/* @TODO split this out once it works as it broke all the tests :( */
toMock() {
let _store2 = this.store,
url = _store2.url,
params = _store2.params,
data = _store2.data,
method = _store2.method; // eslint-disable-next-line
const nock = require("nock");
const mockUrl = process.env.BASE_URL || 'http://localhost:4000'; // console.log('mock data', this.store)
// @NOTE naming it apiUrl was better, oops
// show helpful messages to make sure people use it
this.validateRequestStore(); // for now, autofix it to include the baseUrl
if (!url.includes('http')) {
url = mockUrl + url;
}
const handleGet = urlRequested => {
// `api/${url}`
const doesRequestIncludeUrl = urlRequested.includes(url) || url.includes(urlRequested); // this.log('getCall', { url, urlRequested, doesRequestIncludeUrl })
return doesRequestIncludeUrl;
};
if (this.isPost) {
// console.dev(`${this.store.method} MOCKED`)
return nock(mockUrl).post(url).query(params).reply(201, data);
} else {
// console.dev(`${url} GET Crocked`)
return nock(mockUrl).get(handleGet).query(params).reply(200, data);
}
}
setVariables(variables) {
return this._set('variables', variables);
}
setQuery(Query) {
return this._set('query', Query);
}
gql() {} // all the things
/**
* (subscriber)
* same as () / .call() / .end() / .fetch()
*/
send() {
// @todo
// const response: ApolloQueryResult<Query> = await client.query(args)
// subscriber
return this.toRequest().apply(this, arguments);
}
}
exports.Request = Request;
Object.defineProperty(Request, "middleware", {
configurable: true,
enumerable: true,
writable: true,
value: new Map()
}); // export default Request