@taraai/read-write
Version:
Synchronous NoSQL/Firestore for React
128 lines (110 loc) • 3.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.mapWithFirebaseAndDispatch = mapWithFirebaseAndDispatch;
exports.wrapInDispatch = wrapInDispatch;
var _isFunction = _interopRequireDefault(require("lodash/isFunction"));
var _isObject = _interopRequireDefault(require("lodash/isObject"));
var _mapValues = _interopRequireDefault(require("lodash/mapValues"));
var _mutate = _interopRequireDefault(require("./mutate"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function makePayload(_ref, valToPass) {
let {
payload
} = _ref;
return typeof payload === 'function' ? payload(valToPass) : payload;
}
function wrapInDispatch(dispatch, _ref2) {
let {
ref = {},
meta = {},
method,
args = [],
types
} = _ref2;
if (!(0, _isFunction.default)(dispatch)) {
throw new Error('dispatch is not a function');
}
const [requestingType, successType, errorType] = types;
const startAction = {
type: (0, _isObject.default)(requestingType) ? requestingType.type : requestingType,
meta,
payload: (0, _isObject.default)(requestingType) ? requestingType.payload : {
args
}
};
const optimistic = new Promise((resolve, reject) => {
Object.defineProperty(startAction, '_promise', {
enumerable: false,
configurable: false,
writable: false,
value: {
resolve,
reject
}
});
if (method !== 'mutate') {
resolve();
}
dispatch(startAction);
});
if ((ref && ref.options && ref.options.databaseURL || null) === null) return Promise.resolve();
const saved = method === 'mutate' ? (0, _mutate.default)(ref, ...args) : ref[method](...args);
saved.then(result => {
const successIsObject = (0, _isObject.default)(successType);
const actionObj = {
type: successIsObject ? successType.type : successType,
meta,
payload: successIsObject && successType.payload ? makePayload(successType, result) : {
args
}
};
if (successIsObject && successType.preserve) {
actionObj.preserve = successType.preserve;
}
if (successIsObject && successType.merge) {
actionObj.merge = successType.merge;
}
dispatch(actionObj);
return result;
}).catch(err => {
dispatch({
type: errorType,
meta,
payload: err
});
return err;
});
return new Promise((done, error) => {
Promise.race([new Promise(resolve => setTimeout(resolve, 30000, ['timeout'])), Promise.allSettled([saved, optimistic])]).then(_ref3 => {
let [firestore, memory] = _ref3;
if (firestore === 'timeout') return error(`Timed out after 30 seconds when saving ${JSON.stringify(args)}.`);
if (memory.status === 'rejected') return error(memory.reason);
if (firestore.status === 'rejected') return error(firestore.reason);
return done(firestore.value);
});
});
}
function createWithFirebaseAndDispatch(firebase, dispatch) {
return func => function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return func.apply(firebase, [firebase, dispatch, ...args]);
};
}
function mapWithFirebaseAndDispatch(firebase, dispatch, actions, aliases) {
const withFirebaseAndDispatch = createWithFirebaseAndDispatch(firebase, dispatch);
return { ...(0, _mapValues.default)(actions, withFirebaseAndDispatch),
...aliases.reduce((acc, _ref4) => {
let {
action,
name
} = _ref4;
return { ...acc,
[name]: withFirebaseAndDispatch(action)
};
}, {})
};
}