@nfq/react-ssr
Version:
An helper bundle for react with ssr setup
193 lines (163 loc) • 5.54 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.storeFactory = exports.storeMap = exports.registerStore = exports.getStoreIdent = exports.DataConnector = void 0;
var _reactEasyState = require("@risingstack/react-easy-state");
var _propTypes = _interopRequireDefault(require("prop-types"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const storeMap = {};
/**
* Creates stores usable for front and backend and also the needed functions and api's to work together.
*
* @param {String} name The store name. (Best is to use the same name as the variable has the store is saved in).
* @param {Object} storeData The data the store has in it. (Functions and properties.)
*
* @returns {Proxy} An store proxy.
*/
exports.storeMap = storeMap;
const storeFactory = (name, storeData) => {
const storeDataName = getStoreIdent(name);
const data = Object.keys(storeData).reduce((acc, val) => {
// eslint-disable-next-line security/detect-object-injection
if (typeof storeData[val] === 'function') {
// eslint-disable-next-line security/detect-object-injection
acc.storeFunc[val] = storeData[val];
} else {
// eslint-disable-next-line security/detect-object-injection
acc.storeData[val] = storeData[val];
}
return acc;
}, {
storeData: {},
storeFunc: {}
});
const storeResult = (0, _reactEasyState.store)({
data: { ...data.storeData
},
...data.storeFunc,
initData() {
if (typeof window !== 'undefined') {
// eslint-disable-next-line security/detect-object-injection
if (window[storeDataName]) {
// eslint-disable-next-line security/detect-object-injection
this.data = window[storeDataName];
}
}
}
});
storeResult.initData();
registerStore(storeDataName, storeResult);
return storeResult;
};
/**
* Gets the store ident used for the name given.
*
* @param {String} name The store name used to create an store.
*
* @returns {String} The store data ident.
*/
exports.storeFactory = storeFactory;
const getStoreIdent = name => `__${name.toUpperCase()}__`;
/**
* Registers an created store to the store map.
*
* @param {String} name The store map ident (usually the same as the data ident).
* @param {Proxy} storeObj The store proxy object.
*/
exports.getStoreIdent = getStoreIdent;
const registerStore = (name, storeObj) => {
// eslint-disable-next-line security/detect-object-injection
if (typeof storeMap[name] === 'undefined') {
// eslint-disable-next-line security/detect-object-injection
storeMap[name] = storeObj;
}
};
/**
* An higher order component class that gives an Screen component all needed functionallity to load and retrieve data on server and client.
*
* @param {Object} Class The class to add the functionallity to.
* @param {Array} UsedStores An array of objects that have the following properties: {name: String, functions: Array}
*
* @returns {Object} Returns an new class with all functions needed.
*/
exports.registerStore = registerStore;
const DataConnector = (Class, UsedStores) => {
var _class, _temp;
const storeInfo = UsedStores.map(storeData => {
// eslint-disable-next-line no-param-reassign
storeData.name = getStoreIdent(storeData.name);
return storeData;
});
return _temp = _class = class ConnectedClass extends Class {
/**
* Fetches data from Store.
*
* @static
* @param {Function} fetch The fetch function. (fetch in browser, node-fetch in node).
* @param {Object} storeObj The storeObject.
* @param {String} func The function name to use.
* @param {String} [id=null] The data id for this store.
*
* @memberof ConnectedClass
*/
static async fetchData(fetch, storeObj, func, id = null) {
// eslint-disable-next-line security/detect-object-injection
return storeObj[func](fetch, id);
}
/**
* Creates an instance of ConnectedClass.
*
* @param {Object} props Component props.
*
* @memberof ConnectedClass
*/
constructor(props) {
super(props);
const {
staticContext
} = props;
if (staticContext) {
const usableIdents = ConnectedClass.storeIdents.map(item => item.name);
staticContext.stores.filter(item => usableIdents.includes(item.dataId)).forEach(storeData => {
storeMap[storeData.dataId].data = storeData.storeData;
});
}
}
/**
* Fetches data.
*
* @memberof ConnectedClass
*/
componentDidMount() {
const {
contentId,
match
} = this.props;
const stores = UsedStores.map(storeData => ({ ...storeData,
store: storeMap[storeData.name]
}));
let id;
if (match) {
id = match.params.id;
} else if (contentId) {
id = contentId;
}
stores.forEach(storeData => {
storeData.functions.forEach(func => {
ConnectedClass.fetchData(fetch, storeData.store, func, id);
});
});
if (typeof super.componentDidMount === 'function') {
super.componentDidMount();
}
}
}, _class.propTypes = {
match: _propTypes.default.object,
staticContext: _propTypes.default.object
}, _class.defaultProps = {
match: null,
staticContext: null
}, _class.storeIdents = storeInfo, _temp;
};
exports.DataConnector = DataConnector;
;