@shopgate/pwa-common 7.8.1 → 7.9.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/App.js CHANGED
@@ -1,11 +1,13 @@
1
- function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a 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);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}import React,{Component}from'react';import PropTypes from'prop-types';import{Provider}from'react-redux';import{CookiesProvider}from'react-cookie';import{loadCustomStyles}from'@shopgate/engage/styles';import ErrorBoundary from"./components/ErrorBoundary";import{appDidStart}from"./action-creators/app";import I18n from"./components/I18n";/**
1
+ import _regeneratorRuntime from"@babel/runtime/regenerator";function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{Promise.resolve(value).then(_next,_throw);}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value);}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err);}_next(undefined);});};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a 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);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}import React,{Component}from'react';import PropTypes from'prop-types';import{Provider}from'react-redux';import{CookiesProvider}from'react-cookie';import{loadCustomStyles}from'@shopgate/engage/styles';import ErrorBoundary from"./components/ErrorBoundary";import{appDidStart}from"./action-creators/app";import I18n from"./components/I18n";import{getIsSessionExpired}from"./selectors/user";import logout from"./actions/user/logout";/**
2
2
  * The application component.
3
3
  * It sets up the store and the react router. The router's children (routes) come from
4
4
  * the theme's Main.jsx file which uses this component as the root element.
5
5
  * @returns {JSX}
6
6
  */var App=/*#__PURE__*/function(_Component){_inherits(App,_Component);function App(){_classCallCheck(this,App);return _possibleConstructorReturn(this,_getPrototypeOf(App).apply(this,arguments));}_createClass(App,[{key:"componentDidMount",/**
7
7
  * Registers the component for the native events and fires the onload AppCommand.
8
- */value:function componentDidMount(){this.props.store.dispatch(appDidStart("".concat(window.location.pathname).concat(window.location.search)));loadCustomStyles();}/**
8
+ */value:function componentDidMount(){var _this=this;/**
9
+ * Async helper function that performs optional steps before appDidStart action is dispatched
10
+ */var performAppStart=/*#__PURE__*/function(){var _ref=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1){switch(_context.prev=_context.next){case 0:if(!getIsSessionExpired(_this.props.store.getState())){_context.next=3;break;}_context.next=3;return _this.props.store.dispatch(logout(undefined,true));case 3:_this.props.store.dispatch(appDidStart("".concat(window.location.pathname).concat(window.location.search)));case 4:case"end":return _context.stop();}}},_callee);}));return function performAppStart(){return _ref.apply(this,arguments);};}();performAppStart();loadCustomStyles();}/**
9
11
  * Renders the component.
10
12
  * @returns {JSX}
11
13
  */},{key:"render",value:function render(){return React.createElement(CookiesProvider,null,React.createElement(ErrorBoundary,{key:"error.root",store:this.props.store,isRoot:true},React.createElement(Provider,{store:this.props.store},React.createElement(I18n.Provider,null,React.createElement("div",null,this.props.children)))));}}]);return App;}(Component);export default App;
@@ -10,8 +10,9 @@ import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,ERROR_LEGACY_CONNECT_REGISTER,REQ
10
10
  * Creates the dispatched RECEIVE_LOGIN action object.
11
11
  * @param {string} redirect The location to redirect to.
12
12
  * @param {string} strategy The login strategy.
13
+ * @param {number} [sessionLifetimeInSeconds] The session lifetime in seconds
13
14
  * @returns {Object} The dispatched action object.
14
- */export var successLogin=function successLogin(redirect){var strategy=arguments.length>1&&arguments[1]!==undefined?arguments[1]:DEFAULT_LOGIN_STRATEGY;return{type:SUCCESS_LOGIN,redirect:redirect,strategy:strategy};};/**
15
+ */export var successLogin=function successLogin(redirect){var strategy=arguments.length>1&&arguments[1]!==undefined?arguments[1]:DEFAULT_LOGIN_STRATEGY;var sessionLifetimeInSeconds=arguments.length>2?arguments[2]:undefined;return{type:SUCCESS_LOGIN,redirect:redirect,strategy:strategy,sessionLifetimeInSeconds:sessionLifetimeInSeconds};};/**
15
16
  * Creates the dispatched ERROR_LOGIN action object.
16
17
  * @param {Array} [messages=[]] Array of error messages.
17
18
  * @param {string} code The specific error code.
@@ -25,12 +26,14 @@ import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,ERROR_LEGACY_CONNECT_REGISTER,REQ
25
26
  */export var requestLogout=function requestLogout(){return{type:REQUEST_LOGOUT};};/**
26
27
  * Creates the dispatched RECEIVE_LOGOUT action object.
27
28
  * @param {boolean} [notify=true] If set to TRUE users are notified when the logout was successful.
29
+ * @param {boolean} [autoLogout=false] Whether the logout happened because e.g. session expired
28
30
  * @returns {Object} The dispatched action object.
29
- */export var successLogout=function successLogout(){var notify=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;return{type:SUCCESS_LOGOUT,notify:notify};};/**
31
+ */export var successLogout=function successLogout(){var notify=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;var autoLogout=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;return{type:SUCCESS_LOGOUT,notify:notify,autoLogout:autoLogout};};/**
30
32
  * Creates the dispatched ERROR_LOGOUT action object.
31
33
  * @param {Array} [messages=[]] Array of error messages
34
+ * @param {boolean} [autoLogout=false] Whether the logout happened because e.g. session expired
32
35
  * @returns {Object} The dispatched action object.
33
- */export var errorLogout=function errorLogout(){var messages=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];return{type:ERROR_LOGOUT,messages:messages};};/**
36
+ */export var errorLogout=function errorLogout(){var messages=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var autoLogout=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;return{type:ERROR_LOGOUT,messages:messages,autoLogout:autoLogout};};/**
34
37
  * Creates the dispatched REQUEST_USER action object.
35
38
  * @returns {Object} The dispatched action object.
36
39
  */export var requestUser=function requestUser(){return{type:REQUEST_USER};};/**
@@ -1,2 +1,2 @@
1
- import{requestLogin,successLogin,errorLogin,requestLogout,successLogout,errorLogout,requestUser,receiveUser,errorUser,toggleLoggedIn}from"./index";import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,REQUEST_LOGOUT,SUCCESS_LOGOUT,ERROR_LOGOUT,REQUEST_USER,RECEIVE_USER,ERROR_USER,TOGGLE_LOGGED_IN}from"../../constants/ActionTypes";import{DEFAULT_LOGIN_STRATEGY}from"../../constants/user";var messages=[{type:'EUNKNOWN',message:'Something went wrong',code:1337}];describe('Action Creators: user',function(){describe('requestLogin()',function(){it('should work as expected',function(){var user='super@user.com';var password='super#password';var expected={type:REQUEST_LOGIN,user:user,password:password,strategy:DEFAULT_LOGIN_STRATEGY};expect(requestLogin(user,password)).toEqual(expected);});});describe('successLogin()',function(){it('should work as expected with no parameters',function(){var expected={type:SUCCESS_LOGIN,redirect:undefined,strategy:DEFAULT_LOGIN_STRATEGY};expect(successLogin()).toEqual(expected);});it('should work as expected with parameters',function(){var redirect='/some/url';var strategy='custom';var expected={type:SUCCESS_LOGIN,redirect:redirect,strategy:strategy};expect(successLogin(redirect,strategy)).toEqual(expected);});});describe('errorLogin()',function(){it('should work as expected',function(){var expected={type:ERROR_LOGIN,code:'EUNKNOWN',messages:messages};expect(errorLogin(messages,'EUNKNOWN')).toEqual(expected);});it('should work as expected when the messages parameter is empty',function(){var expected={type:ERROR_LOGIN,code:'EUNKNOWN',messages:[]};expect(errorLogin(undefined,'EUNKNOWN')).toEqual(expected);});it('should work as expected when the code paramter is empty',function(){var expected={type:ERROR_LOGIN,code:'',messages:messages};expect(errorLogin(messages)).toEqual(expected);});});describe('requestLogout()',function(){it('should work as expected',function(){var expected={type:REQUEST_LOGOUT};expect(requestLogout()).toEqual(expected);});});describe('successLogout()',function(){it('should work as expected when called without parameter',function(){var expected={type:SUCCESS_LOGOUT,notify:true};expect(successLogout()).toEqual(expected);});it('should work as expected when called with true',function(){var expected={type:SUCCESS_LOGOUT,notify:true};expect(successLogout(true)).toEqual(expected);});it('should work as expected when called with false',function(){var expected={type:SUCCESS_LOGOUT,notify:false};expect(successLogout(false)).toEqual(expected);});});describe('errorLogout()',function(){it('should work as expected',function(){var expected={type:ERROR_LOGOUT,messages:messages};expect(errorLogout(messages)).toEqual(expected);});it('should work as expected when the messages parameter is empty',function(){var expected={type:ERROR_LOGOUT,messages:[]};expect(errorLogout()).toEqual(expected);});});describe('requestUser()',function(){it('should work as expected',function(){var expected={type:REQUEST_USER};expect(requestUser()).toEqual(expected);});});describe('receiveUser()',function(){it('should work as expected',function(){var user={firstName:'John',lastName:'Doe',mail:'john@doe.com'};var expected={type:RECEIVE_USER,user:user};expect(receiveUser(user)).toEqual(expected);});});describe('errorUser()',function(){it('should work as expected',function(){var err=new Error();// eslint-disable-next-line extra-rules/no-single-line-objects
1
+ import{requestLogin,successLogin,errorLogin,requestLogout,successLogout,errorLogout,requestUser,receiveUser,errorUser,toggleLoggedIn}from"./index";import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,REQUEST_LOGOUT,SUCCESS_LOGOUT,ERROR_LOGOUT,REQUEST_USER,RECEIVE_USER,ERROR_USER,TOGGLE_LOGGED_IN}from"../../constants/ActionTypes";import{DEFAULT_LOGIN_STRATEGY}from"../../constants/user";var messages=[{type:'EUNKNOWN',message:'Something went wrong',code:1337}];describe('Action Creators: user',function(){describe('requestLogin()',function(){it('should work as expected',function(){var user='super@user.com';var password='super#password';var expected={type:REQUEST_LOGIN,user:user,password:password,strategy:DEFAULT_LOGIN_STRATEGY};expect(requestLogin(user,password)).toEqual(expected);});});describe('successLogin()',function(){it('should work as expected with no parameters',function(){var expected={type:SUCCESS_LOGIN,redirect:undefined,strategy:DEFAULT_LOGIN_STRATEGY};expect(successLogin()).toEqual(expected);});it('should work as expected with parameters',function(){var redirect='/some/url';var strategy='custom';var expected={type:SUCCESS_LOGIN,redirect:redirect,strategy:strategy};expect(successLogin(redirect,strategy)).toEqual(expected);});});describe('errorLogin()',function(){it('should work as expected',function(){var expected={type:ERROR_LOGIN,code:'EUNKNOWN',messages:messages};expect(errorLogin(messages,'EUNKNOWN')).toEqual(expected);});it('should work as expected when the messages parameter is empty',function(){var expected={type:ERROR_LOGIN,code:'EUNKNOWN',messages:[]};expect(errorLogin(undefined,'EUNKNOWN')).toEqual(expected);});it('should work as expected when the code paramter is empty',function(){var expected={type:ERROR_LOGIN,code:'',messages:messages};expect(errorLogin(messages)).toEqual(expected);});});describe('requestLogout()',function(){it('should work as expected',function(){var expected={type:REQUEST_LOGOUT};expect(requestLogout()).toEqual(expected);});});describe('successLogout()',function(){it('should work as expected when called without parameter',function(){var expected={type:SUCCESS_LOGOUT,notify:true,autoLogout:false};expect(successLogout()).toEqual(expected);});it('should work as expected when called with true',function(){var expected={type:SUCCESS_LOGOUT,notify:true,autoLogout:false};expect(successLogout(true)).toEqual(expected);});it('should work as expected when called with false',function(){var expected={type:SUCCESS_LOGOUT,notify:false,autoLogout:false};expect(successLogout(false)).toEqual(expected);});it('should work as expected when called with autoLogout parameter',function(){var expected={type:SUCCESS_LOGOUT,notify:true,autoLogout:true};expect(successLogout(undefined,true)).toEqual(expected);});});describe('errorLogout()',function(){it('should work as expected',function(){var expected={type:ERROR_LOGOUT,messages:messages,autoLogout:false};expect(errorLogout(messages)).toEqual(expected);});it('should work as expected when the messages parameter is empty',function(){var expected={type:ERROR_LOGOUT,messages:[],autoLogout:false};expect(errorLogout()).toEqual(expected);});it('should work as expected when called with autoLogout parameter',function(){var expected={type:ERROR_LOGOUT,messages:messages,autoLogout:true};expect(errorLogout(messages,true)).toEqual(expected);});});describe('requestUser()',function(){it('should work as expected',function(){var expected={type:REQUEST_USER};expect(requestUser()).toEqual(expected);});});describe('receiveUser()',function(){it('should work as expected',function(){var user={firstName:'John',lastName:'Doe',mail:'john@doe.com'};var expected={type:RECEIVE_USER,user:user};expect(receiveUser(user)).toEqual(expected);});});describe('errorUser()',function(){it('should work as expected',function(){var err=new Error();// eslint-disable-next-line extra-rules/no-single-line-objects
2
2
  var expected={type:ERROR_USER,error:err};expect(errorUser(err)).toEqual(expected);});});describe('toggleLoggedIn()',function(){it('should toggle to true',function(){var expected={type:TOGGLE_LOGGED_IN,value:true};expect(toggleLoggedIn(true)).toEqual(expected);});it('should toggle to false',function(){var expected={type:TOGGLE_LOGGED_IN,value:false};expect(toggleLoggedIn(false)).toEqual(expected);});});});
@@ -6,7 +6,7 @@ import{PipelineRequest,EINVALIDCALL,ELEGACYSGCONNECT,EINCOMPLETELOGIN}from'@shop
6
6
  * @param {string} redirect The location to redirect to when logged in.
7
7
  * @param {string} strategy basic or facebook, amazon, etc
8
8
  * @return {Function} A redux thunk.
9
- */function login(parameters,redirect){var strategy=arguments.length>2&&arguments[2]!==undefined?arguments[2]:DEFAULT_LOGIN_STRATEGY;return function(dispatch){dispatch(requestLogin(parameters.login,parameters.password,strategy));var request=new PipelineRequest(SHOPGATE_USER_LOGIN_USER).setTrusted().setErrorBlacklist([EINVALIDCALL,ELEGACYSGCONNECT,EINCOMPLETELOGIN]).setInput({strategy:strategy,parameters:parameters}).dispatch();request.then(function(result){var success=result.success,messages=result.messages;if(success){dispatch(successLogin(redirect,strategy));}else{dispatch(errorLogin(messages));}})["catch"](function(error){var code=error.code;if(code===EINVALIDCALL){/**
9
+ */function login(parameters,redirect){var strategy=arguments.length>2&&arguments[2]!==undefined?arguments[2]:DEFAULT_LOGIN_STRATEGY;return function(dispatch){dispatch(requestLogin(parameters.login,parameters.password,strategy));var request=new PipelineRequest(SHOPGATE_USER_LOGIN_USER).setTrusted().setErrorBlacklist([EINVALIDCALL,ELEGACYSGCONNECT,EINCOMPLETELOGIN]).setInput({strategy:strategy,parameters:parameters}).dispatch();request.then(function(result){var success=result.success,messages=result.messages,sessionLifetimeInSeconds=result.sessionLifetimeInSeconds;if(success){dispatch(successLogin(redirect,strategy,sessionLifetimeInSeconds));}else{dispatch(errorLogin(messages));}})["catch"](function(error){var code=error.code;if(code===EINVALIDCALL){/**
10
10
  * This code is thrown when the login request failed, because the user was already logged
11
11
  * in. In that situation the success action can also dispatch to trigger the necessary
12
12
  * processes which has to happen after a successful login.
@@ -1,5 +1,6 @@
1
1
  import{PipelineRequest}from'@shopgate/pwa-core';import{requestLogout,successLogout,errorLogout}from"../../action-creators/user";import{SHOPGATE_USER_LOGOUT_USER}from"../../constants/Pipelines";import{mutable}from"../../helpers/redux";/**
2
2
  * Logout the current user.
3
3
  * @param {boolean} [notify=true] If set to TRUE users are notified when the logout was successful.
4
+ * @param {boolean} [autoLogout=false] Whether the logout happened because session expired
4
5
  * @return {Function} A redux thunk.
5
- */function logout(){var notify=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;return function(dispatch){dispatch(requestLogout());var request=new PipelineRequest(SHOPGATE_USER_LOGOUT_USER).setTrusted().dispatch();request.then(function(result){var success=result.success,messages=result.messages;if(success){dispatch(successLogout(notify));}else{dispatch(errorLogout(messages));}})["catch"](function(){dispatch(errorLogout());});return request;};}/** @mixes {MutableFunction} */export default mutable(logout);
6
+ */function logout(){var notify=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;var autoLogout=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;return function(dispatch){dispatch(requestLogout());var request=new PipelineRequest(SHOPGATE_USER_LOGOUT_USER).setTrusted().dispatch();request.then(function(result){var success=result.success,messages=result.messages;if(success){dispatch(successLogout(notify,autoLogout));}else{dispatch(errorLogout(messages,autoLogout));}})["catch"](function(){dispatch(errorLogout(undefined,autoLogout));});return request;};}/** @mixes {MutableFunction} */export default mutable(logout);
@@ -1,8 +1,8 @@
1
- import React from'react';import{mount}from'enzyme';import{JSDOM}from'jsdom';import{embeddedMedia}from'@shopgate/pwa-common/collections';import HtmlSanitizer from"./index";jest.mock('@shopgate/pwa-common/collections/EmbeddedMedia',function(){return{add:jest.fn(),remove:jest.fn()};});jest.mock("../EmbeddedMedia",function(){return function(_ref){var children=_ref.children;return children;};});/**
1
+ function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import React from'react';import{mount}from'enzyme';import{JSDOM}from'jsdom';import{embeddedMedia}from'@shopgate/pwa-common/collections';import HtmlSanitizer from"./index";jest.mock('@shopgate/pwa-common/collections/EmbeddedMedia',function(){return{add:jest.fn(),remove:jest.fn()};});jest.mock("../EmbeddedMedia",function(){return function(_ref){var children=_ref.children;return children;};});/**
2
2
  * @param {string} html HTML markup.
3
3
  * @param {Object} props Component props.
4
4
  * @returns {JSX}
5
- */var createWrapper=function createWrapper(html){var props=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return mount(React.createElement(HtmlSanitizer,props,html));};describe('<HtmlSanitizer />',function(){beforeEach(function(){jest.clearAllMocks();});it('should render the HtmlSanitizer',function(){/**
5
+ */var createWrapper=function createWrapper(html){var props=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return mount(React.createElement(HtmlSanitizer,_extends({navigate:function navigate(){}},props),html));};describe('<HtmlSanitizer />',function(){beforeEach(function(){jest.clearAllMocks();});it('should render the HtmlSanitizer',function(){/**
6
6
  * The value for html is the HTML-escaped equivalent of the following:
7
7
  * <h1>Hello World!</h1>
8
8
  * @type {string}
@@ -15,4 +15,4 @@ expect(wrapper.html()).toEqual('<div><h1>Hello World!</h1></div>');expect(wrappe
15
15
  * <script>var y = 23;</script>
16
16
  * @type {string}
17
17
  */var html='&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js&quot;&gt;&lt;/script&gt; &lt;script type=&quot;text/javascript&quot;&gt;var x = 42;&lt;/script&gt; &lt;p&gt;Foo Bar&lt;/p&gt; &lt;script&gt;var y = 23;&lt;/script&gt;';var wrapper=createWrapper(html,{decode:true});// Test result of dangerouslySetInnerHTML.
18
- expect(wrapper.html()).toEqual('<div> <p>Foo Bar</p> </div>');expect(wrapper).toMatchSnapshot();});describe('Link handling',function(){var mockedHandleClick=jest.fn();beforeEach(function(){mockedHandleClick.mockClear();});it('follows a link from a plain <a>',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; href=&quot;#follow-me-and-everything-is-alright&quot;&gt;Plain Link&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];aTag.closest=function(){return aTag;};var event={target:aTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#follow-me-and-everything-is-alright','');});it('follows a link from a <a> with other HTML inside',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; target=&quot;_blank&quot; href=&quot;#I-ll-be-the-one-to-tuck-you-in-at-night&quot;&gt;&lt;span&gt;Span Link&lt;/span&gt;&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];var spanTag=doc.getElementsByTagName('span')[0];spanTag.closest=function(){return aTag;};var event={target:spanTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#I-ll-be-the-one-to-tuck-you-in-at-night','_blank');});});});
18
+ expect(wrapper.html()).toEqual('<div> <p>Foo Bar</p> </div>');expect(wrapper).toMatchSnapshot();});describe('Link handling',function(){var mockedHandleClick=jest.fn();beforeEach(function(){mockedHandleClick.mockClear();});it('follows a link from a plain <a>',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; href=&quot;#follow-me-and-everything-is-alright&quot;&gt;Plain Link&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];aTag.closest=function(){return aTag;};var event={target:aTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#follow-me-and-everything-is-alright','');});it('follows a link from a <a> with other HTML inside',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; target=&quot;_blank&quot; href=&quot;#I-ll-be-the-one-to-tuck-you-in-at-night&quot;&gt;&lt;span&gt;Span Link&lt;/span&gt;&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];var spanTag=doc.getElementsByTagName('span')[0];spanTag.closest=function(){return aTag;};var event={target:spanTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#I-ll-be-the-one-to-tuck-you-in-at-night','_blank');});});});
@@ -54,10 +54,10 @@ if(!this.props.enablePromiseBasedLoading){this.isLoading=false;}}/**
54
54
  * Tests if all items have been received and are visible based on current offset.
55
55
  * @param {Object} [props] The current or next component props.
56
56
  * @returns {boolean}
57
- */},{key:"allItemsAreRendered",value:function allItemsAreRendered(){var props=arguments.length>0&&arguments[0]!==undefined?arguments[0]:this.props;var _this$state$offset2=_slicedToArray(this.state.offset,2),offset=_this$state$offset2[0],limit=_this$state$offset2[1];if(props.enablePromiseBasedLoading){var totalItems=props.totalItems;// At promise based loading the offset is increased after the response came in.
57
+ */},{key:"allItemsAreRendered",value:function allItemsAreRendered(){var props=arguments.length>0&&arguments[0]!==undefined?arguments[0]:this.props;var totalItems=props.totalItems,items=props.items;var _this$state$offset2=_slicedToArray(this.state.offset,2),offset=_this$state$offset2[0],limit=_this$state$offset2[1];if(props.enablePromiseBasedLoading){// At promise based loading the offset is increased after the response came in.
58
58
  // This method is invoked to evaluate if a new request needs to be dispatched, so we check
59
59
  // against the current offset state.
60
- return totalItems!==null&&offset>=totalItems;}return!this.needsToReceiveItems(props)&&offset+limit>=props.totalItems;}/**
60
+ return totalItems!==null&&(offset>=totalItems||offset===0&&Array.isArray(items)&&items.length===totalItems);}return!this.needsToReceiveItems(props)&&offset+limit>=totalItems;}/**
61
61
  * Increases the current offset by limit (from props).
62
62
  * @returns {Object}
63
63
  */},{key:"increaseOffset",value:function increaseOffset(){var _this$state$offset3=_slicedToArray(this.state.offset,2),start=_this$state$offset3[0],length=_this$state$offset3[1];var newOffset=start+length;/**
@@ -1,4 +1,4 @@
1
- function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a 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);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _get(target,property,receiver){if(typeof Reflect!=="undefined"&&Reflect.get){_get=Reflect.get;}else{_get=function _get(target,property,receiver){var base=_superPropBase(target,property);if(!base)return;var desc=Object.getOwnPropertyDescriptor(base,property);if(desc.get){return desc.get.call(receiver);}return desc.value;};}return _get(target,property,receiver||target);}function _superPropBase(object,property){while(!Object.prototype.hasOwnProperty.call(object,property)){object=_getPrototypeOf(object);if(object===null)break;}return object;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}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;}import React from'react';import classNames from'classnames';import{logger}from'@shopgate/pwa-core';import SimpleInput from"./SimpleInput";/**
1
+ function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a 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);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _get(target,property,receiver){if(typeof Reflect!=="undefined"&&Reflect.get){_get=Reflect.get;}else{_get=function _get(target,property,receiver){var base=_superPropBase(target,property);if(!base)return;var desc=Object.getOwnPropertyDescriptor(base,property);if(desc.get){return desc.get.call(receiver);}return desc.value;};}return _get(target,property,receiver||target);}function _superPropBase(object,property){while(!Object.prototype.hasOwnProperty.call(object,property)){object=_getPrototypeOf(object);if(object===null)break;}return object;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}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;}import React from'react';import classNames from'classnames';import{logger}from'@shopgate/pwa-core';import SimpleInput from"./SimpleInput";/**
2
2
  * A component that takes care of rendering and validation of input fields.
3
3
  * This component has no styling and should not be used directly.
4
4
  * You may want to use an appropriate form field component from the template instead.
@@ -23,4 +23,4 @@ this.doComponentDidMount();}/**
23
23
  */value:function handleRef(ref){_get(_getPrototypeOf(MultiLineInput.prototype),"handleRef",this).call(this,ref);this.setBaseHeight();}/**
24
24
  * Renders the component.
25
25
  * @returns {JSX}
26
- */},{key:"render",value:function render(){var _this2=this;var _this$props=this.props,className=_this$props.className,password=_this$props.password;var type=password?'password':this.props.type;var value=this.state.value;return React.createElement("textarea",{id:this.props.id,name:this.props.name,ref:function ref(_ref){return _this2.handleRef(_ref);},className:classNames(className,'multiLineInput'),type:type,value:value,onChange:this.handleChange,onFocus:this.handleFocus,onBlur:this.handleBlur,disabled:this.props.disabled});}}]);return MultiLineInput;}(SimpleInput);export default MultiLineInput;
26
+ */},{key:"render",value:function render(){var _this2=this;var _this$props=this.props,className=_this$props.className,password=_this$props.password,attributes=_this$props.attributes;var type=password?'password':this.props.type;var value=this.state.value;return React.createElement("textarea",_extends({id:this.props.id,name:this.props.name,ref:function ref(_ref){return _this2.handleRef(_ref);},className:classNames(className,'multiLineInput'),type:type,value:value,onChange:this.handleChange,onFocus:this.handleFocus,onBlur:this.handleBlur,disabled:this.props.disabled},attributes));}}]);return MultiLineInput;}(SimpleInput);export default MultiLineInput;
package/constants/user.js CHANGED
@@ -1 +1,3 @@
1
- export var DEFAULT_LOGIN_STRATEGY='basic';export var EVENT_USER_INITIALIZED='EVENT_USER_INITIALIZED';
1
+ export var DEFAULT_LOGIN_STRATEGY='basic';export var EVENT_USER_INITIALIZED='EVENT_USER_INITIALIZED';/**
2
+ * Defines the interval to check if an expirable session is expired
3
+ */export var SESSION_EXPIRY_CHECK_INTERVAL=20*1000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopgate/pwa-common",
3
- "version": "7.8.1",
3
+ "version": "7.9.0-beta.1",
4
4
  "description": "Common library for the Shopgate Connect PWA.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Shopgate <support@shopgate.com>",
@@ -16,7 +16,7 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@sentry/browser": "6.0.1",
19
- "@shopgate/pwa-benchmark": "7.8.1",
19
+ "@shopgate/pwa-benchmark": "7.9.0-beta.1",
20
20
  "@virtuous/conductor": "~2.5.0",
21
21
  "@virtuous/react-conductor": "~2.5.0",
22
22
  "@virtuous/redux-persister": "1.1.0-beta.7",
@@ -44,7 +44,7 @@
44
44
  "url-search-params": "^0.10.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@shopgate/pwa-core": "7.8.1",
47
+ "@shopgate/pwa-core": "7.9.0-beta.1",
48
48
  "lodash": "^4.17.4",
49
49
  "prop-types": "~15.7.2",
50
50
  "react": "~16.12.0",
@@ -1,6 +1,6 @@
1
- function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import{APP_DID_START,REQUEST_LOGIN,SUCCESS_LOGIN,TOGGLE_LOGGED_IN,ERROR_LOGIN,SUCCESS_LOGOUT,DISABLE_LOGIN}from"../../constants/ActionTypes";var defaultState={isFetching:false,disabled:false,isLoggedIn:false,errors:null,strategy:null};/**
1
+ function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import{APP_DID_START,REQUEST_LOGIN,SUCCESS_LOGIN,TOGGLE_LOGGED_IN,ERROR_LOGIN,SUCCESS_LOGOUT,DISABLE_LOGIN}from"../../constants/ActionTypes";var defaultState={isFetching:false,disabled:false,isLoggedIn:false,errors:null,strategy:null,expires:null};/**
2
2
  * Stores the login state
3
3
  * @param {Object} [state] The current state.
4
4
  * @param {Object} action The action object.
5
5
  * @return {Object} The new state.
6
- */export default function userLoginReducer(){var state=arguments.length>0&&arguments[0]!==undefined?arguments[0]:defaultState;var action=arguments.length>1?arguments[1]:undefined;switch(action.type){case APP_DID_START:return _extends({},state,{disabled:false});case DISABLE_LOGIN:return _extends({},state,{disabled:action.value});case REQUEST_LOGIN:return _extends({},state,{strategy:action.strategy,isFetching:true});case SUCCESS_LOGIN:return _extends({},state,{isLoggedIn:true,errors:null,isFetching:false,strategy:action.strategy});case ERROR_LOGIN:return _extends({},state,{errors:action.messages,isLoggedIn:false,isFetching:false});case TOGGLE_LOGGED_IN:return _extends({},state,{isLoggedIn:action.value,strategy:null});case SUCCESS_LOGOUT:return defaultState;default:return state;}}
6
+ */export default function userLoginReducer(){var state=arguments.length>0&&arguments[0]!==undefined?arguments[0]:defaultState;var action=arguments.length>1?arguments[1]:undefined;switch(action.type){case APP_DID_START:return _extends({},state,{disabled:false});case DISABLE_LOGIN:return _extends({},state,{disabled:action.value});case REQUEST_LOGIN:return _extends({},state,{strategy:action.strategy,isFetching:true});case SUCCESS_LOGIN:return _extends({},state,{isLoggedIn:true,errors:null,isFetching:false,strategy:action.strategy},typeof action.sessionLifetimeInSeconds==='number'?{expires:new Date().getTime()+action.sessionLifetimeInSeconds*1000}:{expires:null});case ERROR_LOGIN:return _extends({},state,{errors:action.messages,isLoggedIn:false,isFetching:false});case TOGGLE_LOGGED_IN:return _extends({},state,{isLoggedIn:action.value,strategy:null},action.value===false?{expires:null}:null);case SUCCESS_LOGOUT:return defaultState;default:return state;}}
@@ -1,4 +1,4 @@
1
- import{createSelector}from'reselect';import{isObject}from"../helpers/validation";/**
1
+ import{createSelector}from'reselect';import{isObject}from"../helpers/validation";import authRoutes from"../collections/AuthRoutes";/**
2
2
  * @param {Object} state The application state.
3
3
  * @return {Object}
4
4
  */export var getRouterState=function getRouterState(state){return state.router;};/**
@@ -59,4 +59,7 @@ import{createSelector}from'reselect';import{isObject}from"../helpers/validation"
59
59
  * @param {Object} state The application state.
60
60
  * @param {Object} props The component props.
61
61
  * @returns {Object} The route.
62
- */createSelector(getRouterStack,getRouterStackIndex,function(routerStack,routerStackIndex){var sliced=routerStack.slice(0,routerStackIndex);var reversedIndex=sliced.reverse().findIndex(function(route){return route.pattern===pattern;});return reversedIndex===-1?reversedIndex:sliced.length-1-reversedIndex;}));};
62
+ */createSelector(getRouterStack,getRouterStackIndex,function(routerStack,routerStackIndex){var sliced=routerStack.slice(0,routerStackIndex);var reversedIndex=sliced.reverse().findIndex(function(route){return route.pattern===pattern;});return reversedIndex===-1?reversedIndex:sliced.length-1-reversedIndex;}));};/**
63
+ * Creates a selector to determine if the current active route is "protected" (needs login).
64
+ * @returns {Function}
65
+ */export var makeGetIsCurrentRouteProtected=function makeGetIsCurrentRouteProtected(){return createSelector(getCurrentPathname,function(pattern){return!!authRoutes.getProtector(pattern);});};
package/selectors/user.js CHANGED
@@ -33,4 +33,13 @@ import{createSelector}from'reselect';import{getUrl}from"./url";/**
33
33
  * Gets the register url.
34
34
  * @param {Object} state The application state.
35
35
  * @return {string|null}
36
- */export var getRegisterUrl=function getRegisterUrl(state){return getUrl(state,{type:'register'});};
36
+ */export var getRegisterUrl=function getRegisterUrl(state){return getUrl(state,{type:'register'});};/**
37
+ * Retrieves the expiry timestamp from the user login storage
38
+ */export var getSessionExpiry=createSelector(getLoginData,function(loginData){return loginData.expires;});/**
39
+ * Checks if the current session is expired.
40
+ *
41
+ * !!! CAUTION Not implemented with createSelector since selector caching conflicts with processing
42
+ * the current timestamp
43
+ * @param {Object} state The application state.
44
+ * @returns {boolean}
45
+ */export var getIsSessionExpired=function getIsSessionExpired(state){var expiry=getSessionExpiry(state);return typeof expiry==='number'&&new Date().getTime()>=expiry;};
package/store/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import{composeWithDevTools}from'redux-devtools-extension';import{createStore,applyMiddleware}from'redux';import thunk from'redux-thunk';import{persistState}from'@virtuous/redux-persister';import benchmarkMiddleware from'@shopgate/pwa-benchmark/profilers/redux';import benchmarkController from'@shopgate/pwa-benchmark';import persistedReducers from"../collections/PersistedReducers";import initSubscribers from"../subscriptions";import appConfig,{themeName,shopNumber}from"../helpers/config";import makeRootReducer from"../reducers";import streams from"./middelwares/streams";import logger from"./middelwares/logger";/**
1
+ function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}import{createStore,applyMiddleware,compose}from'redux';import thunk from'redux-thunk';import{persistState}from'@virtuous/redux-persister';import benchmarkMiddleware from'@shopgate/pwa-benchmark/profilers/redux';import benchmarkController from'@shopgate/pwa-benchmark';import persistedReducers from"../collections/PersistedReducers";import initSubscribers from"../subscriptions";import appConfig,{themeName,shopNumber}from"../helpers/config";import makeRootReducer from"../reducers";import streams from"./middelwares/streams";import logger from"./middelwares/logger";/**
2
2
  * The current version of the state created by this reducer.
3
3
  * @type {string}
4
- */var STATE_VERSION='v2';var storeKey="shopgate-connect_".concat(shopNumber,"-").concat(themeName,"_").concat(STATE_VERSION);/**
4
+ */var STATE_VERSION='v3';var storeKey="shopgate-connect_".concat(shopNumber,"-").concat(themeName,"_").concat(STATE_VERSION);/**
5
5
  * Returns a normalized initialState from the localstorage.
6
6
  * @returns {Object}
7
7
  */function getInitialState(){if(!window.localStorage){return undefined;}var storedState=window.localStorage.getItem(storeKey);if(!storedState){return undefined;}var normalizedState=storedState.replace(new RegExp('"isFetching":true','g'),'"isFetching":false');return JSON.parse(normalizedState);}/**
@@ -10,7 +10,7 @@ import{composeWithDevTools}from'redux-devtools-extension';import{createStore,app
10
10
  * @param {Array} subscribers The subscribers to the streams middleware.
11
11
  * @return {Object} The redux store.
12
12
  */export function configureStore(reducers,subscribers){// Starts benchmark controller BEFORE adding the middleware.
13
- if(appConfig.benchmark){benchmarkController.startup();}var store=createStore(makeRootReducer(reducers),getInitialState(),composeWithDevTools(applyMiddleware.apply(void 0,[thunk].concat(appConfig.benchmark?[benchmarkMiddleware]:[],[streams,logger])),persistState({key:storeKey,paths:persistedReducers.getAll()})));initSubscribers(subscribers);if(window.Cypress){window.store=store;}return store;}/**
13
+ if(appConfig.benchmark){benchmarkController.startup();}var composeWithDevTools=(typeof window==="undefined"?"undefined":_typeof(window))==='object'&&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__:compose;var store=createStore(makeRootReducer(reducers),getInitialState(),composeWithDevTools(applyMiddleware.apply(void 0,[thunk].concat(appConfig.benchmark?[benchmarkMiddleware]:[],[streams,logger])),persistState({key:storeKey,paths:persistedReducers.getAll()})));initSubscribers(subscribers);if(window.Cypress){window.store=store;}return store;}/**
14
14
  * Configures a mocked store for tests.
15
15
  * @param {Function} reducers The reducers to use in the mock store.
16
16
  * @param {Array} subscribers Streams subscribers to initialize.
package/streams/user.js CHANGED
@@ -1,4 +1,4 @@
1
- import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,ERROR_LEGACY_CONNECT_REGISTER,REQUEST_LOGOUT,SUCCESS_LOGOUT,RECEIVE_USER,ERROR_USER}from"../constants/ActionTypes";import{appDidStart$}from"./app";import{main$}from"./main";/**
1
+ import{Observable}from'rxjs/Observable';import'rxjs/add/observable/interval';import'rxjs/add/operator/takeUntil';import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,ERROR_LEGACY_CONNECT_REGISTER,REQUEST_LOGOUT,SUCCESS_LOGOUT,RECEIVE_USER,ERROR_USER}from"../constants/ActionTypes";import{appDidStart$}from"./app";import{main$}from"./main";import{SESSION_EXPIRY_CHECK_INTERVAL}from"../constants/user";import{getSessionExpiry,getIsSessionExpired}from"../selectors/user";/**
2
2
  * Gets triggered when user is requesting to login.
3
3
  * @type {Observable}
4
4
  */export var userWillLogin$=main$.filter(function(_ref){var action=_ref.action;return action.type===REQUEST_LOGIN;});/**
@@ -29,4 +29,14 @@ import{REQUEST_LOGIN,SUCCESS_LOGIN,ERROR_LOGIN,ERROR_LEGACY_CONNECT_REGISTER,REQ
29
29
  */export var loginDidFail$=main$.filter(function(_ref9){var action=_ref9.action;return action.type===ERROR_LOGIN;});/**
30
30
  * Gets triggered when the legacy sgconnect registration failed
31
31
  * @type {Observable}
32
- */export var legacyConnectRegisterDidFail$=main$.filter(function(_ref10){var action=_ref10.action;return action.type===ERROR_LEGACY_CONNECT_REGISTER;});
32
+ */export var legacyConnectRegisterDidFail$=main$.filter(function(_ref10){var action=_ref10.action;return action.type===ERROR_LEGACY_CONNECT_REGISTER;});/**
33
+ * Emits when user session expiry needs to be checked. That's the case when the login state in
34
+ * Redux contains a numeric value for the "expires" property.
35
+ * Checks are performed at appStart since there might be a persisted value in Redux from the last
36
+ * sessions, or it happens after login when the login response contained a session lease.
37
+ */export var sessionExpiryNeedsToBeChecked$=appDidStart$.merge(userDidLogin$).filter(function(_ref11){var getState=_ref11.getState;var expiry=getSessionExpiry(getState());return expiry!==null;});/**
38
+ * Emits when a user session with an expiry expires. Therefore it performs an interval check to
39
+ * check if the session is still active.
40
+ */export var userSessionExpired$=sessionExpiryNeedsToBeChecked$.switchMap(function(data){// At first check if the session already expired - necessary for appDidStart$
41
+ if(getIsSessionExpired(data.getState())){return Observable.of(data);}// Setup an interval that periodically checks if the session expired - runs till user logged out
42
+ return Observable.interval(SESSION_EXPIRY_CHECK_INTERVAL).takeUntil(userDidLogout$).filter(function(){return getIsSessionExpired(data.getState());}).switchMap(function(){return Observable.of(data);});});
@@ -1,7 +1,9 @@
1
- import{event}from'@shopgate/pwa-core';import{hasWebBridge,INDEX_PATH}from'@shopgate/engage/core';import{routeDidChange$,userDidLogout$}from"../streams";import{historyReset,historyResetTo}from"../actions/router";/**
1
+ import{event}from'@shopgate/pwa-core';import{hasWebBridge,INDEX_PATH}from'@shopgate/engage/core';import{routeDidChange$,userDidLogout$}from"../streams";import{historyReset,historyResetTo}from"../actions/router";import{makeGetIsCurrentRouteProtected}from"../selectors/router";/**
2
2
  * History subscriptions.
3
3
  * @param {Function} subscribe The subscribe function.
4
- */export default function history(subscribe){subscribe(userDidLogout$,function(_ref){var dispatch=_ref.dispatch;if(hasWebBridge()){// Within the website there is no guarantee that the index page is the first stack entry
4
+ */export default function history(subscribe){subscribe(userDidLogout$,function(_ref){var dispatch=_ref.dispatch,action=_ref.action,getState=_ref.getState;var isAutoLogout=action.autoLogout;if(isAutoLogout&&!makeGetIsCurrentRouteProtected()(getState())){// When users where automatically logged out, we only redirect to the index screen if
5
+ // currently a route is active that needs a login.
6
+ return;}if(hasWebBridge()){// Within the website there is no guarantee that the index page is the first stack entry
5
7
  dispatch(historyResetTo(INDEX_PATH));}else{dispatch(historyReset());}});/**
6
8
  * @deprecated Will be removed in Next versions
7
9
  */subscribe(routeDidChange$,function(){event.trigger('routeDidChange');});}
@@ -1,6 +1,6 @@
1
- import{getCurrentRoute}from'@shopgate/pwa-common/selectors/router';import event from'@shopgate/pwa-core/classes/Event';import registerEvents from'@shopgate/pwa-core/commands/registerEvents';import{LoadingProvider}from"../providers";import{fetchUser}from"../actions/user";import{successLogin}from"../action-creators";import{historyPush}from"../actions/router";import{appDidStart$,userWillLogin$,userLoginResponse$,userDidLogin$,userDidLogout$,userDidInitialize$,legacyConnectRegisterDidFail$}from"../streams";import showModal from"../actions/modal/showModal";import{LOGIN_PATH}from"../constants/RoutePaths";import{LEGACY_URL_CONNECT_REGISTER}from"../constants/Registration";import{EVENT_USER_INITIALIZED}from"../constants/user";/**
1
+ import _regeneratorRuntime from"@babel/runtime/regenerator";function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{Promise.resolve(value).then(_next,_throw);}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value);}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err);}_next(undefined);});};}import{getCurrentRoute}from'@shopgate/pwa-common/selectors/router';import event from'@shopgate/pwa-core/classes/Event';import registerEvents from'@shopgate/pwa-core/commands/registerEvents';import{LoadingProvider}from"../providers";import{fetchUser}from"../actions/user";import{successLogin}from"../action-creators";import{historyPush}from"../actions/router";import logout from"../actions/user/logout";import{appDidStart$,userWillLogin$,userLoginResponse$,userDidLogin$,userDidLogout$,userDidInitialize$,legacyConnectRegisterDidFail$,userSessionExpired$}from"../streams";import showModal from"../actions/modal/showModal";import{LOGIN_PATH}from"../constants/RoutePaths";import{LEGACY_URL_CONNECT_REGISTER}from"../constants/Registration";import{EVENT_USER_INITIALIZED}from"../constants/user";/**
2
2
  * User subscriptions.
3
3
  * @param {Function} subscribe The subscribe function.
4
4
  */export default function user(subscribe){/**
5
5
  * Gets triggered when ever the user data need to be updated.
6
- */var userNeedsUpdate$=appDidStart$.merge(userDidLogin$);subscribe(userDidInitialize$,function(_ref){var events=_ref.events;events.emit(EVENT_USER_INITIALIZED);});subscribe(userWillLogin$,function(){LoadingProvider.setLoading(LOGIN_PATH);});subscribe(userLoginResponse$,function(){LoadingProvider.unsetLoading(LOGIN_PATH);});subscribe(userNeedsUpdate$,function(_ref2){var dispatch=_ref2.dispatch;dispatch(fetchUser());});subscribe(userDidLogout$,function(_ref3){var dispatch=_ref3.dispatch,action=_ref3.action;if(action.notify===false){return;}dispatch(showModal({confirm:'modal.ok',dismiss:null,message:'login.logout_message',title:null}));});subscribe(appDidStart$,function(_ref4){var dispatch=_ref4.dispatch,getState=_ref4.getState;registerEvents(['userLoggedIn']);event.addCallback('userLoggedIn',function(){var _getCurrentRoute=getCurrentRoute(getState()),_getCurrentRoute$stat=_getCurrentRoute.state;_getCurrentRoute$stat=_getCurrentRoute$stat===void 0?{}:_getCurrentRoute$stat;var redirect=_getCurrentRoute$stat.redirect;dispatch(successLogin(redirect));});});subscribe(legacyConnectRegisterDidFail$,function(_ref5){var dispatch=_ref5.dispatch;dispatch(historyPush({pathname:LEGACY_URL_CONNECT_REGISTER}));});}
6
+ */var userNeedsUpdate$=appDidStart$.merge(userDidLogin$);subscribe(userDidInitialize$,function(_ref){var events=_ref.events;events.emit(EVENT_USER_INITIALIZED);});subscribe(userWillLogin$,function(){LoadingProvider.setLoading(LOGIN_PATH);});subscribe(userLoginResponse$,function(){LoadingProvider.unsetLoading(LOGIN_PATH);});subscribe(userNeedsUpdate$,function(_ref2){var dispatch=_ref2.dispatch;dispatch(fetchUser());});subscribe(userDidLogout$,/*#__PURE__*/function(){var _ref4=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref3){var dispatch,action,isAutoLogout,confirmed;return _regeneratorRuntime.wrap(function _callee$(_context){while(1){switch(_context.prev=_context.next){case 0:dispatch=_ref3.dispatch,action=_ref3.action;if(!(action.notify===false)){_context.next=3;break;}return _context.abrupt("return");case 3:isAutoLogout=action.autoLogout;_context.next=6;return dispatch(showModal(_extends({confirm:'modal.ok',dismiss:null,message:'login.logout_message',title:null},isAutoLogout?{message:'login.auto_logout_message',confirm:'modal.login',dismiss:'modal.close'}:null)));case 6:confirmed=_context.sent;if(isAutoLogout&&confirmed){dispatch(historyPush({pathname:LOGIN_PATH}));}case 8:case"end":return _context.stop();}}},_callee);}));return function(_x){return _ref4.apply(this,arguments);};}());subscribe(appDidStart$,function(_ref5){var dispatch=_ref5.dispatch,getState=_ref5.getState;registerEvents(['userLoggedIn']);event.addCallback('userLoggedIn',function(){var _getCurrentRoute=getCurrentRoute(getState()),_getCurrentRoute$stat=_getCurrentRoute.state;_getCurrentRoute$stat=_getCurrentRoute$stat===void 0?{}:_getCurrentRoute$stat;var redirect=_getCurrentRoute$stat.redirect;dispatch(successLogin(redirect));});});subscribe(legacyConnectRegisterDidFail$,function(_ref6){var dispatch=_ref6.dispatch;dispatch(historyPush({pathname:LEGACY_URL_CONNECT_REGISTER}));});subscribe(userSessionExpired$,function(_ref7){var dispatch=_ref7.dispatch;dispatch(logout(undefined,true));});}