directlink-react
Version:
DirectLink is a library for building single-page web applications that makes the world easier for ASP.NET Core developers who use React.
675 lines (611 loc) • 25.3 kB
JavaScript
(function(e, a) { for(var i in a) e[i] = a[i]; }(window, /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
;
/* WEBPACK VAR INJECTION */(function(global) {
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
// Copyright (c) 2018 Andrei Molchanov. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
/*global React, ReactDOM, components, signalR*/
var Utils = __webpack_require__(2);
var DefferedPromise = Utils.DeferredPromise;
var directlink = {
data: {},
instances: {},
scripts: {},
styles: {},
promises: {},
nocache: false,
hmr: false,
renderApp: function renderApp(container, data) {
directlink.container = container;
directlink.hub.start().then(function () {
if (data) {
directlink.render(data);
} else {
directlink.requestData(window.location.pathname);
}
window.onpopstate = directlink.history.popState;
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
directlink.history.current = { path: location.pathname, hash: location.hash };
}).catch(function (error) {
container.innerHTML = '';
throw error || 'start signalr connection failed';
});
},
render: function render(data, requestAssets) {
var requests = [];
if (requestAssets) {
var timestamp = directlink.nocache ? '?_=' + Date.now() : '';
for (var name in data.Scripts) {
if (directlink.scripts[name] !== data.Scripts[name]) {
requests.push(Utils.getScript(data.Scripts[name] + timestamp));
}
}
for (var _name in data.Styles) {
if (directlink.styles[_name] !== data.Styles[_name]) {
requests.push(Utils.getStyle(data.Styles[_name] + timestamp));
}
}
}
Promise.all(requests).then(function () {
directlink.scripts = Object.assign(directlink.scripts, data.Scripts);
directlink.styles = Object.assign(directlink.styles, data.Styles);
directlink.data = data;
document.title = data.Title;
if (!directlink.rendered) {
var render = directlink.container.childElementCount ? ReactDOM.hydrate : ReactDOM.render;
if (directlink.hmr) {
directlink.instances.HMR = render(React.createElement(HMR, { component: data.App }), directlink.container, directlink.onRendered);
} else {
render(React.createElement(components[data.App]), directlink.container, directlink.onRendered);
}
} else {
for (var key in data.States) {
var instance = directlink.instances[key];
if (instance) {
instance.setState(data.States[key]);
}
}
if (directlink.forceUpdate) {
directlink.instances.HMR.forceUpdate();
delete directlink.forceUpdate;
} else {
directlink.scrollIntoView(location.hash);
}
}
});
},
onRendered: function onRendered() {
directlink.rendered = true;
directlink.linked = Promise['resolve']();
directlink.scrollIntoView(location.hash);
},
init: function init(instance) {
instance.name = Utils.getClassName(instance);
instance.scope = instance.props.scope || instance.context && instance.context.scope;
if (instance.scope) {
instance.fullname = instance.scope + '.' + instance.name;
}
if (instance.props.fullname) {
instance.fullname = instance.props.fullname;
}
if (!instance.fullname) {
instance.fullname = instance.name;
}
if (instance.props.id) {
instance.fullname += '$' + instance.props.id;
}
instance.state = directlink.data.States[instance.fullname] || {};
if (instance.name === directlink.data.App) {
instance.state.online = true;
}
if (global.signalR) {
directlink.instances[instance.fullname] = instance;
instance.invoke = function (method, args) {
var invocationId = Utils.getGuid();
var promise = new DefferedPromise(function (resolve, reject) {
directlink.online().then(function () {
return directlink.linked;
}).then(function () {
if (args && !Array.isArray(args)) {
args = [args];
}
directlink.hub.instance.invoke("invoke", invocationId, instance.fullname, instance.name, method, args).catch(function (error) {
delete directlink.promises[invocationId];
reject(error);
});
}).catch(function (error) {
return reject(error);
});
});
directlink.promises[invocationId] = promise;
return promise;
};
for (var i in directlink.data.Methods[instance.name]) {
var method = directlink.data.Methods[instance.name][i];
instance[method] = function (method) {
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return instance.invoke(method, [].concat(args));
};
}(method);
}
if (directlink.data.Bidirectional.indexOf(instance.name) !== -1) {
instance.bidirectional = true;
directlink.link(instance);
}
instance.updateId = function (id) {
directlink.unlink(instance);
delete directlink.instances[instance.fullname];
if (instance.fullname.indexOf('$') > 0) {
instance.fullname = instance.fullname.replace('$' + instance.props.id, '$' + id);
}
directlink.instances[instance.fullname] = instance;
directlink.link(instance);
};
}
},
link: function link(instance) {
var props = Object.assign({}, instance.props);
delete props.scope;
delete props.fullname;
directlink.hub.instance.invoke("link", instance.fullname, instance.name, props);
},
unlink: function unlink(instance) {
return directlink.hub.instance.invoke("unlink", instance.fullname, instance.name);
},
dispose: function dispose(instance) {
if (!directlink.hmr) {
if (instance.bidirectional) {
directlink.unlink(instance);
}
delete directlink.instances[instance.fullname];
}
},
requestData: function requestData(path, referer) {
return directlink.hub.instance.invoke("requestData", path, referer);
},
hub: {
instance: null,
connectionId: function connectionId() {
return directlink.hub.instance && directlink.hub.instance.connection.connectionId;
},
init: function init() {
var hub = new signalR.HubConnectionBuilder().withUrl("/directlink").configureLogging(signalR.LogLevel.Information).build();
hub.on("SetState", function (fullname, state) {
if (directlink.instances.hasOwnProperty(fullname)) {
directlink.instances[fullname].setState(state);
}
});
hub.on("Invoke", function (fullname, method, args) {
if (directlink.instances.hasOwnProperty(fullname)) {
if (args) {
var _directlink$instances;
(_directlink$instances = directlink.instances[fullname])[method].apply(_directlink$instances, _toConsumableArray(args));
} else {
directlink.instances[fullname][method]();
}
}
});
hub.on("DataResponse", function (result) {
if (result.Data) {
directlink.render(result.Data, true);
return;
}
throw 'status code ' + result.StatusCode;
});
hub.on("InvokeResult", function (invocationId, response) {
var promise = directlink.promises[invocationId];
delete directlink.promises[invocationId];
if (response && response.StatusCode === 200) {
if (response.Result !== undefined) {
promise.resolve(response.Result);
} else {
promise.resolve();
}
return;
}
promise.reject(response && response.StatusCode ? 'status code ' + response.StatusCode : 'unexpected result');
});
hub.on("AssetsUpdate", function () {
if (directlink.hmr) {
directlink.forceUpdate = true;
directlink.requestData(window.location.pathname);
}
});
var onClose = function onClose(error) {
if (error) {
console.error(error);
}
directlink.instances[directlink.data.App].setState({ online: false });
directlink.hub.reconnect('closed');
};
if (hub.onclose) {
hub.onclose(onClose);
} else {
hub.onClosed = onClose;
}
directlink.hub.instance = hub;
},
state: '',
start: function start() {
directlink.hub.init();
return directlink.hub.instance.start().then(function () {
directlink.hub.reconnectCount = 0;
directlink.hub.state = 'connected';
if (directlink.rendered) {
directlink.linked = new Promise(function (resolve) {
for (var key in directlink.instances) {
var instance = directlink.instances[key];
if (instance.bidirectional) {
directlink.link(instance);
}
}
resolve();
});
}
if (directlink.rendered) {
directlink.instances[directlink.data.App].setState({ online: true });
}
}).catch(function (error) {
setTimeout(function () {
directlink.hub.reconnect('failed');
}, 0);
throw error || 'start signalr connection failed';
});
},
stop: function stop() {
return directlink.hub.instance.connection.stop();
},
reconnect: function reconnect(state) {
var hub = directlink.hub;
hub.state = state;
if (state === 'closed' || state === 'waited') {
hub.state = 'reconnecting';
hub.reconnectPromise = hub.start();
}
if (state === 'failed') {
hub.state = 'waiting';
var maxIndex = hub.reconnectTimeouts.length - 1;
directlink.hub.reconnectTimer = setTimeout(function () {
if (hub.state === 'waiting') {
if (hub.reconnectCount < maxIndex) {
hub.reconnectCount++;
}
hub.reconnect('waited');
}
}, hub.reconnectTimeouts[Math.min(hub.reconnectCount, maxIndex)]);
}
},
reconnectPromise: null,
reconnectTimer: null,
reconnectTimeouts: [1000, 5000, 20000, 60000],
reconnectCount: 0
},
online: function online() {
return new Promise(function (resolve, reject) {
var hub = directlink.hub;
if (hub.instance.connection.connectionState === 1) {
resolve();
return;
}
if (hub.state === 'reconnecting') {
hub.reconnectPromise.then(function () {
return resolve();
}).catch(function () {
return reject('not connected');
});
}
if (hub.state === 'waiting') {
clearTimeout(hub.reconnectTimer);
hub.reconnect('waited');
hub.reconnectPromise.then(function () {
return resolve();
}).catch(function () {
return reject('not connected');
});
}
setTimeout(function () {
return reject('not connected');
}, 10000);
});
},
history: {
current: { path: null, hash: null },
pushState: function pushState(state, title, path) {
var hash = '';
var idx = path.indexOf('#');
if (idx === 0) {
hash = path;
if (directlink.history.current.hash !== hash) {
history.pushState(state, title, directlink.history.current.path + hash);
}
directlink.scrollIntoView(hash);
return;
}
if (!path.startsWith('/')) {
var current = directlink.history.current.path;
var base = current.substring(0, current.lastIndexOf('/') + (path.length > 0 ? 1 : 0));
path = base + path;
if (idx > 0) {
idx += base.length;
}
}
if (idx > 0) {
hash = path.substring(idx);
path = path.substring(0, idx);
if (directlink.history.current.path === path) {
if (directlink.history.current.hash !== hash) {
history.pushState(state, title, path + hash);
}
directlink.scrollIntoView(hash);
return;
}
}
history.pushState(state, title, path + hash);
directlink.history.dispatch(path, hash);
},
popState: function popState() {
if (directlink.history.current.path === location.pathname) {
directlink.scrollIntoView(location.hash);
} else {
directlink.history.dispatch(location.pathname, location.hash);
}
},
dispatch: function dispatch(path, hash) {
var referer = directlink.history.current.path;
directlink.history.current = { path: path, hash: hash };
directlink.online().then(function () {
return directlink.requestData(path + hash, referer);
}).catch(function (error) {
return console.error(error);
});
}
},
scrollIntoView: function scrollIntoView(hash) {
if (hash) {
try {
var element = document.querySelector(hash);
if (element !== null) {
element.scrollIntoView({ block: 'start', behavior: 'smooth' });
}
} catch (error) {
console.log(error);
}
return;
}
window.scrollTo(window.scrollX, 0);
}
};
var Link = function Link(props) {
return React.createElement("a", {
style: props.style,
className: props.className,
href: props.href,
onClick: function onClick(event) {
event.preventDefault();
if (typeof props.onClick === "function") {
props.onClick(event);
}
directlink.history.pushState({}, "", props.href);
}
}, props.children);
};
var Render = function Render(props) {
if (!props.component) {
console.error("Render requires 'component' property");
}
var _props = Object.assign({}, props);
delete _props.component;
_props.fullname = props.component && props.component.FullName;
return props.component && React.createElement(components[props.component.Name], _props);
};
var HMR = function (_React$Component) {
_inherits(HMR, _React$Component);
function HMR() {
_classCallCheck(this, HMR);
return _possibleConstructorReturn(this, (HMR.__proto__ || Object.getPrototypeOf(HMR)).apply(this, arguments));
}
_createClass(HMR, [{
key: 'render',
value: function render() {
if (!this.props.component) {
console.error("HMR requires 'component' property");
}
return this.props.component && React.createElement(components[this.props.component]);
}
}]);
return HMR;
}(React.Component);
var Scope = function Scope(props) {
if (!props.name) {
console.error("Scope requires 'name' property");
}
return React.Children.map(props.children, function (child) {
if (React.isValidElement(child)) {
return React.cloneElement(child, { scope: props.name });
}
return child;
});
};
module.exports = {
components: {},
directlink: directlink,
Link: Link,
Render: Render,
HMR: HMR,
Scope: Scope
};
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))
/***/ }),
/* 1 */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1,eval)("this");
} catch(e) {
// This works if the window reference is available
if(typeof window === "object")
g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var chars = '0123456789abcdef'.split('');
var getGuid = function getGuid() {
var uuid = [],
rnd = Math.random,
r = void 0;
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
for (var i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | rnd() * 16;
uuid[i] = chars[i == 19 ? r & 0x3 | 0x8 : r & 0xf];
}
}
return uuid.join('');
};
var getScript = function getScript(url) {
return new Promise(function (resolve, reject) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.addEventListener('load', function () {
return resolve(script);
}, false);
script.addEventListener('error', function () {
return reject(script);
}, false);
document.body.appendChild(script);
});
};
var getStyle = function getStyle(url) {
return new Promise(function (resolve, reject) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
link.addEventListener('load', function () {
return resolve(link);
}, false);
link.addEventListener('error', function () {
return reject(link);
}, false);
document.body.appendChild(link);
});
};
var getClassName = function getClassName(instance) {
if (instance.constructor.name) {
return instance.constructor.name;
}
var regex = new RegExp(/^\s*function\s*(\S*)\s*\(/);
var getClassName = function getClassName(instance) {
return instance.constructor.toString().match(regex)[1];
};
return getClassName(instance);
};
var DeferredPromise = function DeferredPromise(executor) {
var _this = this;
_classCallCheck(this, DeferredPromise);
this._promise = new Promise(function (resolve, reject) {
_this.resolve = resolve;
_this.reject = reject;
executor(resolve, reject);
});
this.then = this._promise.then.bind(this._promise);
this.catch = this._promise.catch.bind(this._promise);
};
module.exports = {
getGuid: getGuid,
getScript: getScript,
getStyle: getStyle,
getClassName: getClassName,
DeferredPromise: DeferredPromise
};
/***/ })
/******/ ])));