@openmrs/esm-routes 5.7.2 → 5.7.3-pre.2113

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.
@@ -1,10 +1,16 @@
1
1
  Browserslist: caniuse-lite is outdated. Please run:
2
2
  npx update-browserslist-db@latest
3
3
  Why you should do it regularly: https://github.com/browserslist/update-db#readme
4
- asset openmrs-esm-utils.js 3.27 KiB [emitted] [minimized] (name: main) 1 related asset
4
+ asset openmrs-esm-utils.js 14.8 KiB [emitted] [minimized] (name: main) 1 related asset
5
+ orphan modules 36.5 KiB [orphan] 7 modules
5
6
  runtime modules 670 bytes 3 modules
6
- orphan modules 7.27 KiB [orphan] 2 modules
7
- built modules 7.36 KiB [built]
8
- ./src/index.ts + 2 modules 7.32 KiB [built] [code generated]
9
- external "@openmrs/esm-utils" 42 bytes [built] [code generated]
10
- webpack 5.88.0 compiled successfully in 15162 ms
7
+ built modules 36.8 KiB [built]
8
+ modules by path external "@openmrs/ 210 bytes
9
+ external "@openmrs/esm-utils" 42 bytes [built] [code generated]
10
+ external "@openmrs/esm-dynamic-loading" 42 bytes [built] [code generated]
11
+ external "@openmrs/esm-config" 42 bytes [built] [code generated]
12
+ external "@openmrs/esm-feature-flags" 42 bytes [built] [code generated]
13
+ external "@openmrs/esm-extensions" 42 bytes [built] [code generated]
14
+ ./src/index.ts + 7 modules 36.5 KiB [built] [code generated]
15
+ external "single-spa" 42 bytes [built] [code generated]
16
+ webpack 5.88.0 compiled successfully in 6760 ms
@@ -1,2 +1,2 @@
1
- System.register(["@openmrs/esm-utils"],(function(r,e){var t={};return{setters:[function(r){t.canAccessStorage=r.canAccessStorage}],execute:function(){r((()=>{"use strict";var r={618:r=>{r.exports=t}},e={};function o(t){var n=e[t];if(void 0!==n)return n.exports;var a=e[t]={exports:{}};return r[t](a,a.exports,o),a.exports}o.d=(r,e)=>{for(var t in e)o.o(e,t)&&!o.o(r,t)&&Object.defineProperty(r,t,{enumerable:!0,get:e[t]})},o.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),o.r=r=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})};var n={};return(()=>{o.r(n),o.d(n,{addRoutesOverride:()=>a,isOpenmrsAppRoutes:()=>c,isOpenmrsRoutes:()=>u,localStorageRoutesPrefix:()=>r,removeRoutesOverride:()=>s,resetAllRoutesOverrides:()=>i});var r="openmrs-routes:";function e(r,e){(null==e||e>r.length)&&(e=r.length);for(var t=0,o=new Array(e);t<e;t++)o[t]=r[t];return o}var t=(0,o(618).canAccessStorage)();function a(r,e){if(t){if("string"==typeof e){if(e.startsWith("http"))return l(r,e);try{var o=JSON.parse(e);if(c(o))return l(r,o);console.error("The supplied routes for ".concat(r," is not a valid OpenmrsAppRoutes object"),e)}catch(e){console.error("Could not add routes override for ".concat(r,": "),e)}}else{if(n=e,null!=(a=URL)&&"undefined"!=typeof Symbol&&a[Symbol.hasInstance]?a[Symbol.hasInstance](n):n instanceof a)return l(r,e.toString());if(c(e))return l(r,e)}var n,a;console.error("Override for ".concat(r," is not in a valid format. Expected either a Javascript Object, a JSON string of a Javascript object, or a URL"),e)}}function s(e){if(t){var o=r+e;localStorage.removeItem(o)}}function i(){if(t)for(var e=window.localStorage,o=0;o<e.length;o++){var n=e.key(o);(null==n?void 0:n.startsWith(r))&&e.removeItem(n)}}function l(e,t){var o=r+e;localStorage.setItem(o,JSON.stringify(t))}function c(r){if(r&&"object"==typeof r){var e=Object.prototype.hasOwnProperty,t=r;return!!((!e.call(r,"pages")||Boolean(t.pages)&&Array.isArray(t.pages))&&(!e.call(r,"extensions")||Boolean(t.extensions)&&Array.isArray(t.extensions))&&(!e.call(r,"workspaces")||Boolean(t.workspaces)&&Array.isArray(t.workspaces))&&(!e.call(r,"modals")||Boolean(t.modals)&&Array.isArray(t.modals)))}return!1}function u(r){if(r&&"object"==typeof r){var t=r;return Object.entries(t).every((function(r){var t,o,n=(o=2,function(r){if(Array.isArray(r))return r}(t=r)||function(r,e){var t=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null!=t){var o,n,a=[],s=!0,i=!1;try{for(t=t.call(r);!(s=(o=t.next()).done)&&(a.push(o.value),!e||a.length!==e);s=!0);}catch(r){i=!0,n=r}finally{try{s||null==t.return||t.return()}finally{if(i)throw n}}return a}}(t,o)||function(r,t){if(r){if("string"==typeof r)return e(r,t);var o=Object.prototype.toString.call(r).slice(8,-1);return"Object"===o&&r.constructor&&(o=r.constructor.name),"Map"===o||"Set"===o?Array.from(o):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?e(r,t):void 0}}(t,o)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),a=n[0],s=n[1];return"string"==typeof a&&c(s)}))}return!1}})(),n})())}}}));
1
+ System.register(["@openmrs/esm-dynamic-loading","single-spa","@openmrs/esm-config","@openmrs/esm-feature-flags","@openmrs/esm-extensions","@openmrs/esm-utils"],(function(e,n){var t={},o={},r={},i={},a={},s={};return{setters:[function(e){t.importDynamic=e.importDynamic},function(e){o.pathToActiveWhen=e.pathToActiveWhen,o.registerApplication=e.registerApplication},function(e){r.registerModuleWithConfigSystem=e.registerModuleWithConfigSystem},function(e){i.getFeatureFlag=e.getFeatureFlag,i.registerFeatureFlag=e.registerFeatureFlag},function(e){a.attach=e.attach,a.registerExtension=e.registerExtension,a.registerModal=e.registerModal,a.registerWorkspace=e.registerWorkspace},function(e){s.canAccessStorage=e.canAccessStorage}],execute:function(){e((()=>{"use strict";var e={824:e=>{e.exports=r},758:e=>{e.exports=t},45:e=>{e.exports=a},708:e=>{e.exports=i},618:e=>{e.exports=s},645:e=>{e.exports=o}},n={};function c(t){var o=n[t];if(void 0!==o)return o.exports;var r=n[t]={exports:{}};return e[t](r,r.exports,c),r.exports}c.d=(e,n)=>{for(var t in n)c.o(n,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},c.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var l={};return(()=>{c.r(l),c.d(l,{addRoutesOverride:()=>S,finishRegisteringAllApps:()=>O,initializeApp:()=>u,isOpenmrsAppRoutes:()=>E,isOpenmrsRoutes:()=>F,localStorageRoutesPrefix:()=>e,registerApp:()=>w,removeRoutesOverride:()=>T,resetAllRoutesOverrides:()=>P,tryRegisterExtension:()=>y});var e="openmrs-routes:",n=c(758),t={bootstrap:function(){return Promise.resolve()},mount:function(){return Promise.resolve()},unmount:function(){return Promise.resolve()}};function o(e,n,t,o,r,i,a){try{var s=e[i](a),c=s.value}catch(e){return void t(e)}s.done?n(c):Promise.resolve(c).then(o,r)}function r(e){return function(){var n=this,t=arguments;return new Promise((function(r,i){var a=e.apply(n,t);function s(e){o(a,r,i,s,c,"next",e)}function c(e){o(a,r,i,s,c,"throw",e)}s(void 0)}))}}function i(e,n){var t,o,r,i,a={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=1,o&&(r=2&i[0]?o.return:i[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,i[1])).done)return r;switch(o=0,r&&(i=[2&i[0],r.value]),i[0]){case 0:case 1:r=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,o=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((r=(r=a.trys).length>0&&r[r.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!r||i[1]>r[0]&&i[1]<r[3])){a.label=i[1];break}if(6===i[0]&&a.label<r[1]){a.label=r[1],r=i;break}if(r&&a.label<r[2]){a.label=r[2],a.ops.push(i);break}r[2]&&a.ops.pop(),a.trys.pop();continue}i=n.call(e,a)}catch(e){i=[6,e],o=0}finally{t=r=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}}var a=new Map;function s(e,o){return r((function(){var r;return i(this,(function(i){switch(i.label){case 0:return[4,(0,n.importDynamic)(e)];case 1:return(r=i.sent())&&Object.hasOwn(r,o)&&"function"==typeof r[o]?[2,u(e,r).then((function(){return r[o]()}))]:(r&&Object.hasOwn(r,o)?console.warn("The export ".concat(o," of the app ").concat(e," is not a function")):console.warn("The app ".concat(e," does not define a component called ").concat(o,", this cannot be loaded")),[2,t])}}))}))}function u(e,n){return f.apply(this,arguments)}function f(){return(f=r((function(e,t){var o,r;return i(this,(function(i){switch(i.label){case 0:return e in a?[3,5]:null==t?[3,1]:(r=t,[3,3]);case 1:return[4,(0,n.importDynamic)(e)];case 2:r=i.sent(),i.label=3;case 3:return o=r,[4,a[e]=new Promise((function(e,n){if(Object.hasOwn(o,"startupApp")){var t=o.startupApp;if("function"==typeof t)return Promise.resolve(t()).then(e).catch(n)}e(null)}))];case 4:return i.sent(),[3,7];case 5:return[4,a[e]];case 6:i.sent(),i.label=7;case 7:return[2]}}))}))).apply(this,arguments)}var p=c(645),d=c(824),h=c(708),m=c(45);function y(e,n){var t=n.name;if(t){n.slots&&n.slot&&console.warn("The extension ".concat(t," from ").concat(e," declares both a 'slots' property and\na 'slot' property. Only the 'slots' property will be honored."));var o=n.slots?n.slots:n.slot?[n.slot]:[];if(n.component||n.load){var r,i,a=void 0;if(n.component)a=s(e,n.component);else if(n.load){if("function"!=typeof n.load)return void console.error("The extension ".concat(t," from ").concat(e," declares a 'load' property that is not a function. This is not\nsupported, so the extension will not be loaded."));a=n.load}a&&(0,m.registerExtension)({name:t,load:a,meta:n.meta||{},order:n.order,moduleName:e,privileges:n.privileges,online:null===(r=n.online)||void 0===r||r,offline:null!==(i=n.offline)&&void 0!==i&&i,featureFlag:n.featureFlag});var c=!0,l=!1,u=void 0;try{for(var f,p=o[Symbol.iterator]();!(c=(f=p.next()).done);c=!0){var d=f.value;(0,m.attach)(d,t)}}catch(e){l=!0,u=e}finally{try{c||null==p.return||p.return()}finally{if(l)throw u}}}else console.error("The extension ".concat(t," from ").concat(e," is missing a 'component' entry and thus cannot be registered.\nTo fix this, ensure that you define a 'component' field inside the extension definition."),n)}else console.error("An extension definition in ".concat(e,' is missing an name and thus cannot be\nregistered. To fix this, ensure that you define the "name" field inside the\nextension definition.'),n)}function g(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}var v=[];function b(e){if(Array.isArray(e)){var n=e.map(b);return function(e){return n.some((function(n){return n(e)}))}}return"string"==typeof e?(0,p.pathToActiveWhen)(window.getOpenmrsSpaBase()+e):(t=e,(null!=(o=RegExp)&&"undefined"!=typeof Symbol&&o[Symbol.hasInstance]?o[Symbol.hasInstance](t):t instanceof o)?function(n){return function(e,n){return e.test(n.pathname.replace(window.getOpenmrsSpaBase(),""))}(e,n)}:function(){return e});var t,o}function w(e,n){if(e&&n&&"object"==typeof n){var t,o;(0,d.registerModuleWithConfigSystem)(e);var r,i,a,c=null!==(o=n.extensions)&&void 0!==o?o:[],l=null!==(r=n.modals)&&void 0!==r?r:[],u=null!==(i=n.workspaces)&&void 0!==i?i:[],f=null!==(a=n.featureFlags)&&void 0!==a?a:[];null===(t=n.pages)||void 0===t||t.forEach((function(n){var t,o,r;n&&"object"==typeof n&&Object.hasOwn(n,"component")&&(Object.hasOwn(n,"route")||Object.hasOwn(n,"routeRegex")||Object.hasOwn(n,"routes"))?v.push((o=function(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{},o=Object.keys(t);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(t).filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})))),o.forEach((function(n){g(e,n,t[n])}))}return e}({},n),r=null!=(r={order:null!==(t=n.order)&&void 0!==t?t:Number.MAX_SAFE_INTEGER,appName:e})?r:{},Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(r)):function(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t.push.apply(t,o)}return t}(Object(r)).forEach((function(e){Object.defineProperty(o,e,Object.getOwnPropertyDescriptor(r,e))})),o)):console.warn("A page for ".concat(e," could not be registered as it does not appear to have the required properties"),n)})),c.forEach((function(n){n&&"object"==typeof n&&Object.hasOwn(n,"name")&&Object.hasOwn(n,"component")?y(e,n):console.warn("An extension for ".concat(e," could not be registered as it does not appear to have the required properties"),n)})),l.forEach((function(n){n&&"object"==typeof n&&Object.hasOwn(n,"name")&&Object.hasOwn(n,"component")?function(e,n){var t=n.name;if(t)if(n.component||n.load){var o=void 0;if(n.component)o=s(e,n.component);else if(n.load){if("function"!=typeof n.load)return void console.error("The modal ".concat(t," from ").concat(e," declares a 'load' property that is not a function. This is not\nsupported, so the modal will not be loaded."));o=n.load}o&&(0,m.registerModal)({name:t,load:o,moduleName:e})}else console.error("The modal ".concat(t," from ").concat(e," is missing a 'component' entry and thus cannot be registered.\nTo fix this, ensure that you define a 'component' field inside the modal definition."),n);else console.error("A modal definition in ".concat(e,' is missing an name and thus cannot be\nregistered. To fix this, ensure that you define the "name" field inside the\nmodal definition.'),n)}(e,n):console.warn("A modal for ".concat(e," could not be registered as it does not appear to have the required properties"),n)})),u.forEach((function(n){n&&"object"==typeof n&&Object.hasOwn(n,"name")&&Object.hasOwn(n,"component")?function(e,n){var t=n.name;if(t){var o=n.title;if(o)if(n.component||n.load){var r=void 0;if(n.component)r=s(e,n.component);else if(n.load){if("function"!=typeof n.load)return void console.error("The workspace ".concat(t," from ").concat(e," declares a 'load' property that is not a function. This is not\nsupported, so the workspace will not be loaded."));r=n.load}r&&(0,m.registerWorkspace)({name:t,title:o,load:r,moduleName:e,type:n.type,canHide:n.canHide,canMaximize:n.canMaximize,width:n.width,hasOwnSidebar:n.hasOwnSidebar,sidebarFamily:n.sidebarFamily,preferredWindowSize:n.preferredWindowSize})}else console.error("The workspace ".concat(t," from ").concat(e," is missing a 'component' entry and thus cannot be registered.\nTo fix this, ensure that you define a 'component' field inside the workspace definition."),n);else console.error("A workspace definition in ".concat(e,' is missing a title and thus cannot be registered.\nTo fix this, ensure that you define the "title" field inside the workspace definition.'),n)}else console.error("A workspace definition in ".concat(e,' is missing a name and thus cannot be registered.\nTo fix this, ensure that you define the "name" field inside the workspace definition.'),n)}(e,n):console.warn("A workspace for ".concat(e," could not be registered as it does not appear to have the required properties"),n)})),f.forEach((function(n){n&&"object"==typeof n&&Object.hasOwn(n,"featureFlag")?function(e,n){n.flagName?n.label?n.description?(0,h.registerFeatureFlag)(n.flagName,n.label,n.description):console.error("A feature flag definition in ".concat(e,' is missing a description and thus cannot be registered.\nTo fix this, ensure that you define the "description" field inside the feature flag definition.'),n):console.error("A feature flag definition in ".concat(e,' is missing a description and thus cannot be registered.\nTo fix this, ensure that you define the "label" field inside the feature flag definition.'),n):console.error("A feature flag definition in ".concat(e,' is missing a name and thus cannot be registered.\nTo fix this, ensure that you define the "name" field inside the feature flag definition.'),n)}(e,n):console.warn("A feature flag for ".concat(e," could not be registered as it does not appear to have the required properties"),n)}))}}function O(){v.sort((function(e,n){var t=e.order-n.order;return 0!=t?t:e.appName.localeCompare(n.appName,"en")}));var e=new Map,n=!0,t=!1,o=void 0;try{for(var r,i=v[Symbol.iterator]();!(n=(r=i.next()).done);n=!0){var a=r.value;e.has(a.appName)?e.set(a.appName,e.get(a.appName)+1):e.set(a.appName,0);var s=e.get(a.appName),c="".concat(a.appName,"-page-").concat(s),l=document.createElement("div");l.id="single-spa-application:".concat(c),document.body.appendChild(l),x(c,a)}}catch(e){t=!0,o=e}finally{try{n||null==i.return||i.return()}finally{if(t)throw o}}}function x(e,n){var t=void 0!==n.route?n.route:void 0!==n.routeRegex&&new RegExp(n.routeRegex);if(!1!==t)if(n.component){var o=function(e,n){var t=n.online,o=n.offline,r=n.featureFlag;return window.offlineEnabled?function(n){return!!(navigator.onLine&&(null==t||t)||!navigator.onLine&&null!=o&&o)&&!(r&&!(0,h.getFeatureFlag)(r))&&e(n)}:e}(b(t),n),r=s(n.appName,n.component);(0,p.registerApplication)(e,r,o)}else console.warn('A registered page definition is missing a component and thus cannot be registered.\nTo fix this, ensure that you define the "component" field inside the page definition.',e);else console.warn('A registered page definition is missing a route and thus cannot be registered.\nTo fix this, ensure that you define the "route" (or alternatively the "routeRegex") field inside the extension definition.',e)}function A(e,n){(null==n||n>e.length)&&(n=e.length);for(var t=0,o=new Array(n);t<n;t++)o[t]=e[t];return o}var j=(0,c(618).canAccessStorage)();function S(e,n){if(j){if("string"==typeof n){if(n.startsWith("http"))return k(e,n);try{var t=JSON.parse(n);if(E(t))return k(e,t);console.error("The supplied routes for ".concat(e," is not a valid OpenmrsAppRoutes object"),n)}catch(n){console.error("Could not add routes override for ".concat(e,": "),n)}}else{if(o=n,null!=(r=URL)&&"undefined"!=typeof Symbol&&r[Symbol.hasInstance]?r[Symbol.hasInstance](o):o instanceof r)return k(e,n.toString());if(E(n))return k(e,n)}var o,r;console.error("Override for ".concat(e," is not in a valid format. Expected either a Javascript Object, a JSON string of a Javascript object, or a URL"),n)}}function T(n){if(j){var t=e+n;localStorage.removeItem(t)}}function P(){if(j)for(var n=window.localStorage,t=0;t<n.length;t++){var o=n.key(t);(null==o?void 0:o.startsWith(e))&&n.removeItem(o)}}function k(n,t){var o=e+n;localStorage.setItem(o,JSON.stringify(t))}function E(e){if(e&&"object"==typeof e){var n=Object.prototype.hasOwnProperty,t=e;return!!((!n.call(e,"pages")||Boolean(t.pages)&&Array.isArray(t.pages))&&(!n.call(e,"extensions")||Boolean(t.extensions)&&Array.isArray(t.extensions))&&(!n.call(e,"workspaces")||Boolean(t.workspaces)&&Array.isArray(t.workspaces))&&(!n.call(e,"modals")||Boolean(t.modals)&&Array.isArray(t.modals)))}return!1}function F(e){if(e&&"object"==typeof e){var n=e;return Object.entries(n).every((function(e){var n,t,o=(t=2,function(e){if(Array.isArray(e))return e}(n=e)||function(e,n){var t=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=t){var o,r,i=[],a=!0,s=!1;try{for(t=t.call(e);!(a=(o=t.next()).done)&&(i.push(o.value),!n||i.length!==n);a=!0);}catch(e){s=!0,r=e}finally{try{a||null==t.return||t.return()}finally{if(s)throw r}}return i}}(n,t)||function(e,n){if(e){if("string"==typeof e)return A(e,n);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(t):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?A(e,n):void 0}}(n,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),r=o[0],i=o[1];return"string"==typeof r&&E(i)}))}return!1}})(),l})())}}}));
2
2
  //# sourceMappingURL=openmrs-esm-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openmrs-esm-utils.js","mappings":"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","sources":["webpack://@openmrs/esm-routes/external system \"@openmrs/esm-utils\"","webpack://@openmrs/esm-routes/webpack/bootstrap","webpack://@openmrs/esm-routes/webpack/runtime/define property getters","webpack://@openmrs/esm-routes/webpack/runtime/hasOwnProperty shorthand","webpack://@openmrs/esm-routes/webpack/runtime/make namespace object","webpack://@openmrs/esm-routes/./src/constants.ts","webpack://@openmrs/esm-routes/./src/routes.ts"],"sourcesContent":["module.exports = __WEBPACK_EXTERNAL_MODULE__618__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export const localStorageRoutesPrefix = 'openmrs-routes:';\n","/** @module @category Routes Utilities */\nimport type { OpenmrsAppRoutes, OpenmrsRoutes } from '@openmrs/esm-globals';\nimport { canAccessStorage } from '@openmrs/esm-utils';\nimport { localStorageRoutesPrefix } from './constants';\n\nconst isEnabled = canAccessStorage();\n\n/**\n * Used to add a route override to local storage. These are read as the routes registry\n * is assembled, so the app must be reloaded for new overrides to take effect.\n *\n * @internal\n * @param moduleName The name of the module the routes are for\n * @param routes Either an {@link OpenmrsAppRoutes} object, a string that represents a JSON\n * version of an {@link OpenmrsAppRoutes} object or a string or URL that resolves to a\n * JSON document that represents an {@link OpenmrsAppRoutes} object\n */\nexport function addRoutesOverride(moduleName: string, routes: OpenmrsAppRoutes | string | URL) {\n if (!isEnabled) {\n return;\n }\n\n if (typeof routes === 'string') {\n if (routes.startsWith('http')) {\n return addRouteOverrideInternal(moduleName, routes);\n } else {\n try {\n const maybeRoutes = JSON.parse(routes);\n if (isOpenmrsAppRoutes(maybeRoutes)) {\n return addRouteOverrideInternal(moduleName, maybeRoutes);\n } else {\n console.error(`The supplied routes for ${moduleName} is not a valid OpenmrsAppRoutes object`, routes);\n }\n } catch (e) {\n console.error(`Could not add routes override for ${moduleName}: `, e);\n }\n }\n } else if (routes instanceof URL) {\n return addRouteOverrideInternal(moduleName, routes.toString());\n } else if (isOpenmrsAppRoutes(routes)) {\n return addRouteOverrideInternal(moduleName, routes);\n }\n\n console.error(\n `Override for ${moduleName} is not in a valid format. Expected either a Javascript Object, a JSON string of a Javascript object, or a URL`,\n routes,\n );\n}\n\n/**\n * Used to remove an existing routes override from local storage. These are read as the routes registry\n * is assembled, so the app must be reloaded for removed override to be removed.\n *\n * @internal\n * @param moduleName The module to remove the overrides for\n */\nexport function removeRoutesOverride(moduleName: string) {\n if (!isEnabled) {\n return;\n }\n\n const key = localStorageRoutesPrefix + moduleName;\n localStorage.removeItem(key);\n}\n\n/**\n * Used to remove all existing routes overrides from local storage. These are read as the routes registry\n * is assembled, so the app must be reloaded for the removed overrides to appear to be removed.\n *\n * @internal\n */\nexport function resetAllRoutesOverrides() {\n if (!isEnabled) {\n return;\n }\n\n const localStorage = window.localStorage;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(localStorageRoutesPrefix)) {\n localStorage.removeItem(key);\n }\n }\n}\n\nfunction addRouteOverrideInternal(moduleName: string, routes: OpenmrsAppRoutes | string) {\n const key = localStorageRoutesPrefix + moduleName;\n localStorage.setItem(key, JSON.stringify(routes));\n}\n\n/**\n * Simple type-predicate to ensure that the value can be treated as an OpenmrsAppRoutes\n * object.\n *\n * @internal\n * @param routes the object to check to see if it is an OpenmrsAppRoutes object\n * @returns true if the routes value is an OpenmrsAppRoutes\n */\nexport function isOpenmrsAppRoutes(routes: OpenmrsAppRoutes | unknown): routes is OpenmrsAppRoutes {\n if (routes && typeof routes === 'object') {\n const hasOwnProperty = Object.prototype.hasOwnProperty;\n // we cast maybeRoutes as OpenmrsAppRoutes mainly so we can refer to the properties it should\n // have without repeated casts\n const maybeRoutes = routes as OpenmrsAppRoutes;\n\n if (hasOwnProperty.call(routes, 'pages')) {\n if (!Boolean(maybeRoutes.pages) || !Array.isArray(maybeRoutes.pages)) {\n return false;\n }\n }\n\n if (hasOwnProperty.call(routes, 'extensions')) {\n if (!Boolean(maybeRoutes.extensions) || !Array.isArray(maybeRoutes.extensions)) {\n return false;\n }\n }\n\n if (hasOwnProperty.call(routes, 'workspaces')) {\n if (!Boolean(maybeRoutes.workspaces) || !Array.isArray(maybeRoutes.workspaces)) {\n return false;\n }\n }\n\n if (hasOwnProperty.call(routes, 'modals')) {\n if (!Boolean(maybeRoutes.modals) || !Array.isArray(maybeRoutes.modals)) {\n return false;\n }\n }\n\n // Notice that we're essentially testing for things that cannot be treated as an OpenmrsAppRoutes\n // object. This is because a completely empty object is a valid OpenmrsAppRoutes object.\n return true;\n }\n\n return false;\n}\n\n/**\n * Simple type-predicate to ensure that the value can be treated as an OpenmrsRoutes\n * object.\n *\n * @internal\n * @param routes the object to check to see if it is an OpenmrsRoutes object\n * @returns true if the routes value is an OpenmrsRoutes\n */\nexport function isOpenmrsRoutes(routes: OpenmrsRoutes | unknown): routes is OpenmrsRoutes {\n if (routes && typeof routes === 'object') {\n const maybeRoutes = routes as OpenmrsRoutes;\n\n return Object.entries(maybeRoutes).every(([key, value]) => typeof key === 'string' && isOpenmrsAppRoutes(value));\n }\n\n return false;\n}\n"],"names":["module","exports","__WEBPACK_EXTERNAL_MODULE__618__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","d","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag","value","localStorageRoutesPrefix","isEnabled","canAccessStorage","addRoutesOverride","moduleName","routes","startsWith","addRouteOverrideInternal","maybeRoutes","JSON","parse","isOpenmrsAppRoutes","console","error","e","URL","toString","removeRoutesOverride","localStorage","removeItem","resetAllRoutesOverrides","window","i","length","setItem","stringify","Boolean","pages","Array","isArray","extensions","workspaces","modals","isOpenmrsRoutes","entries","every"],"sourceRoot":""}
1
+ {"version":3,"file":"openmrs-esm-utils.js","mappings":"ixBAAAA,EAAOC,QAAUC,C,UCAjBF,EAAOC,QAAUE,C,SCAjBH,EAAOC,QAAUG,C,UCAjBJ,EAAOC,QAAUI,C,UCAjBL,EAAOC,QAAUK,C,UCAjBN,EAAOC,QAAUM,C,GCCbC,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaV,QAGrB,IAAID,EAASQ,EAAyBE,GAAY,CAGjDT,QAAS,CAAC,GAOX,OAHAY,EAAoBH,GAAUV,EAAQA,EAAOC,QAASQ,GAG/CT,EAAOC,OACf,CCrBAQ,EAAoBK,EAAI,CAACb,EAASc,KACjC,IAAI,IAAIC,KAAOD,EACXN,EAAoBQ,EAAEF,EAAYC,KAASP,EAAoBQ,EAAEhB,EAASe,IAC5EE,OAAOC,eAAelB,EAASe,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDP,EAAoBQ,EAAI,CAACK,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFd,EAAoBkB,EAAK1B,IACH,oBAAX2B,QAA0BA,OAAOC,aAC1CX,OAAOC,eAAelB,EAAS2B,OAAOC,YAAa,CAAEC,MAAO,WAE7DZ,OAAOC,eAAelB,EAAS,aAAc,CAAE6B,OAAO,GAAO,E,oSCLvD,IAAMC,EAA2B,kB,SCE3BC,EAAoC,CAC/CC,UAAAA,WACE,OAAOC,QAAQC,SACjB,EACAC,MAAAA,WACE,OAAOF,QAAQC,SACjB,EACAE,QAAAA,WACE,OAAOH,QAAQC,SACjB,G,k2CCKF,IAAMG,EAAkB,IAAIC,IAcrB,SAASC,EAAUC,EAAiBC,GACzC,OAAO,c,IACC1C,E,kDAAS,O,GAAM2C,EAAAA,EAAAA,eAAsBF,I,OAE3C,OAFMzC,EAAS,WAEDkB,OAAO0B,OAAO5C,EAAQ0C,IAA2C,mBAAtB1C,EAAO0C,GACvD,C,EAAAG,EAAcJ,EAASzC,GAAQ8C,MAAK,W,OAAM9C,EAAO0C,I,MAEpD1C,GAAUkB,OAAO0B,OAAO5C,EAAQ0C,GAClCK,QAAQC,KAAK,cAAsCP,OAAxBC,EAAU,gBAAsB,OAARD,EAAQ,uBAE3DM,QAAQC,KAAK,WAAyDN,OAA9CD,EAAQ,wCAAgD,OAAVC,EAAU,4BAI7E,C,EAAAV,I,GACT,GACF,CAgBO,SAAea,EAAcJ,EAAiBzC,G,OAA/B6C,EAAAA,MAAAA,KAAAA,U,UAAAA,I,OAAAA,EAAf,YAA6BJ,EAAiBzC,G,IAE7CiD,EAAAA,E,yDADAR,KAAWH,EAAb,C,WACoBtC,EAAAA,C,QAAAA,E,cAAW,O,GAAM2C,EAAAA,EAAAA,eAAsBF,I,SAA5B,S,iBAEjC,OAFIQ,EAAAA,EAEJ,C,EAAOX,EAAgBG,GAAW,IAAIP,SAAQ,SAACC,EAASe,GACtD,GAAIhC,OAAO0B,OAAOK,EAAS,cAAe,CACxC,IAAME,EAAUF,EAAQ,WACxB,GAAuB,mBAAZE,EACT,OAAOjB,QAAQC,QAAQgB,KAAWL,KAAKX,GAASiB,MAAMF,EAE1D,CAEAf,EAAQ,KACV,K,cATA,S,aAWA,O,EAAMG,EAAgBG,I,OAAtB,S,8BAEJ,KAjBsBI,MAAAA,KAAAA,U,wCCvCf,SAASQ,EAAqBZ,EAAiBa,GACpD,IAAMC,EAAOD,EAAUC,KACvB,GAAKA,EAAL,CAUID,EAAUE,OAASF,EAAUG,MAC/BV,QAAQC,KACN,iBAA8BP,OAAbc,EAAK,UAAgB,OAARd,EAAQ,yGAI1C,IAAMe,EAAQF,EAAUE,MAAQF,EAAUE,MAAQF,EAAUG,KAAO,CAACH,EAAUG,MAAQ,GAEtF,GAAKH,EAAUZ,WAAcY,EAAUI,KAAvC,CASA,IAsBYJ,EACCA,EAvBTK,OAAoD/C,EACxD,GAAI0C,EAAUZ,UACZiB,EAASnB,EAAUC,EAASa,EAAUZ,gBACjC,GAAIY,EAAUI,KAAM,CACzB,GAA8B,mBAAnBJ,EAAUI,KAKnB,YAJAX,QAAQa,MACN,iBAA8BnB,OAAbc,EAAK,UAAgB,OAARd,EAAQ,qHAK1CkB,EAASL,EAAUI,IACrB,CAEIC,IACFE,EAAAA,EAAAA,mBAAkB,CAChBN,KAAAA,EACAG,KAAMC,EACNG,KAAMR,EAAUQ,MAAQ,CAAC,EACzBC,MAAOT,EAAUS,MACjBC,WAAYvB,EACZwB,WAAYX,EAAUW,WACtBC,OAAwB,QAAhBZ,EAAAA,EAAUY,cAAVZ,IAAAA,GAAAA,EACRa,QAA0B,QAAjBb,EAAAA,EAAUa,eAAVb,IAAAA,GAAAA,EACTc,YAAad,EAAUc,c,IAItB,mB,IAAL,QAAK,IAAcZ,EAAAA,OAAAA,cAAd,0BAAqB,CAArB,IAAMC,EAAN,SACHY,EAAAA,EAAAA,QAAOZ,EAAMF,EACf,C,UAFK,Q,aAAA,6B,YAAA,E,MAAA,C,EA9BL,MANER,QAAQa,MACN,iBAA8BnB,OAAbc,EAAK,UAAgB,OAARd,EAAQ,4JAEtCa,EAdJ,MAPEP,QAAQa,MACN,8BAAsC,OAARnB,EAAQ,8IAGtCa,EAqDN,C,wHClEA,IAAMgB,EAAyC,GAY/C,SAASC,EAAcC,GACrB,GAAIC,MAAMC,QAAQF,GAAQ,CACxB,IAAMG,EAAaH,EAAMI,IAAIL,GAC7B,OAAO,SAACM,G,OAAaF,EAAWG,MAAK,SAACC,G,OAAcA,EAAUF,E,IAChE,CAAO,MAAqB,iBAAVL,GACTQ,EAAAA,EAAAA,kBAAiBC,OAAOC,oBAAsBV,I,EAC5CA,G,SAAiBW,S,2FACnB,SAACN,G,OHtBL,SAAoBO,EAAeP,GAExC,OADeO,EAAMC,KAAKR,EAASS,SAASC,QAAQN,OAAOC,oBAAqB,IAElF,CGmByBM,CAAWhB,EAAOK,E,EAEhC,W,OAAML,C,UAEjB,CAgDO,SAASiB,EAAYhD,EAAiBiD,GAC3C,GAAIjD,GAAWiD,GAA4B,iBAAXA,EAAqB,C,IAQnDA,EALwDA,GAFxDC,EAAAA,EAAAA,gCAA+BlD,GAE/B,IACgDiD,EACQA,EACIA,EAHtDE,EAAmE,QAAjBF,EAAAA,EAAOG,kBAAPH,IAAAA,EAAAA,EAAqB,GACvEI,EAAuD,QAAbJ,EAAAA,EAAOK,cAAPL,IAAAA,EAAAA,EAAiB,GAC3DM,EAAmE,QAAjBN,EAAAA,EAAOO,kBAAPP,IAAAA,EAAAA,EAAqB,GACvEQ,EAAyE,QAAnBR,EAAAA,EAAOS,oBAAPT,IAAAA,EAAAA,EAAuB,GAEvE,QAAZA,EAAAA,EAAOpB,aAAPoB,IAAAA,GAAAA,EAAcU,SAAQ,SAACC,G,IASVA,E,IAPTA,GACa,iBAANA,GACPnF,OAAO0B,OAAOyD,EAAG,eAChBnF,OAAO0B,OAAOyD,EAAG,UAAYnF,OAAO0B,OAAOyD,EAAG,eAAiBnF,OAAO0B,OAAOyD,EAAG,WAEjF/B,EAAMgC,M,wUAAK,IACND,G,WAAAA,CACHtC,MAAc,QAAPsC,EAAAA,EAAEtC,aAAFsC,IAAAA,EAAAA,EAAWE,OAAOC,iBACzB/D,QAAAA,I,kVAGFM,QAAQC,KACN,cAAsB,OAARP,EAAQ,kFACtB4D,EAGN,IAEAT,EAAoBQ,SAAQ,SAACK,GACvBA,GAAsB,iBAARA,GAAoBvF,OAAO0B,OAAO6D,EAAK,SAAWvF,OAAO0B,OAAO6D,EAAK,aACrFpD,EAAqBZ,EAASgE,GAE9B1D,QAAQC,KACN,oBAA4B,OAARP,EAAQ,kFAC5BgE,EAGN,IAEAX,EAAgBM,SAAQ,SAACM,GACnBA,GAA0B,iBAAVA,GAAsBxF,OAAO0B,OAAO8D,EAAO,SAAWxF,OAAO0B,OAAO8D,EAAO,aDtC9F,SAA0BjE,EAAiBiE,GAChD,IAAMnD,EAAOmD,EAAMnD,KACnB,GAAKA,EAUL,GAAKmD,EAAMhE,WAAcgE,EAAMhD,KAA/B,CASA,IAAIC,OAAoD/C,EACxD,GAAI8F,EAAMhE,UACRiB,EAASnB,EAAUC,EAASiE,EAAMhE,gBAC7B,GAAIgE,EAAMhD,KAAM,CACrB,GAA0B,mBAAfgD,EAAMhD,KAKf,YAJAX,QAAQa,MACN,aAA0BnB,OAAbc,EAAK,UAAgB,OAARd,EAAQ,iHAKtCkB,EAAS+C,EAAMhD,IACjB,CAEIC,IACFgD,EAAAA,EAAAA,eAAc,CACZpD,KAAAA,EACAG,KAAMC,EACNK,WAAYvB,GApBhB,MANEM,QAAQa,MACN,aAA0BnB,OAAbc,EAAK,UAAgB,OAARd,EAAQ,wJAElCiE,QAbF3D,QAAQa,MACN,yBAAiC,OAARnB,EAAQ,0IAGjCiE,EAmCN,CCHQE,CAAiBnE,EAASiE,GAE1B3D,QAAQC,KACN,eAAuB,OAARP,EAAQ,kFACvBiE,EAGN,IAEAV,EAAoBI,SAAQ,SAACS,GAEzBA,GACqB,iBAAdA,GACP3F,OAAO0B,OAAOiE,EAAW,SACzB3F,OAAO0B,OAAOiE,EAAW,aDH1B,SAA8BpE,EAAiBoE,GACpD,IAAMtD,EAAOsD,EAAUtD,KACvB,GAAKA,EAAL,CASA,IAAMuD,EAAQD,EAAUC,MACxB,GAAKA,EASL,GAAKD,EAAUnE,WAAcmE,EAAUnD,KAAvC,CASA,IAAIC,OAAoD/C,EACxD,GAAIiG,EAAUnE,UACZiB,EAASnB,EAAUC,EAASoE,EAAUnE,gBACjC,GAAImE,EAAUnD,KAAM,CACzB,GAA8B,mBAAnBmD,EAAUnD,KAKnB,YAJAX,QAAQa,MACN,iBAA8BnB,OAAbc,EAAK,UAAgB,OAARd,EAAQ,qHAK1CkB,EAASkD,EAAUnD,IACrB,CAEIC,IACFoD,EAAAA,EAAAA,mBAAkB,CAChBxD,KAAAA,EACAuD,MAAAA,EACApD,KAAMC,EACNK,WAAYvB,EACZuE,KAAMH,EAAUG,KAChBC,QAASJ,EAAUI,QACnBC,YAAaL,EAAUK,YACvBC,MAAON,EAAUM,MACjBC,cAAeP,EAAUO,cACzBC,cAAeR,EAAUQ,cACzBC,oBAAqBT,EAAUS,qBA5BnC,MANEvE,QAAQa,MACN,iBAA8BnB,OAAbc,EAAK,UAAgB,OAARd,EAAQ,4JAEtCoE,QAZF9D,QAAQa,MACN,6BAAqC,OAARnB,EAAQ,8IAErCoE,EAPJ,MANE9D,QAAQa,MACN,6BAAqC,OAARnB,EAAQ,4IAErCoE,EAqDN,CCtDQU,CAAqB9E,EAASoE,GAE9B9D,QAAQC,KACN,mBAA2B,OAARP,EAAQ,kFAC3BoE,EAGN,IAEAX,EAAsBE,SAAQ,SAAChC,GACzBA,GAAsC,iBAAhBA,GAA4BlD,OAAO0B,OAAOwB,EAAa,eDoDhF,SAAgC3B,EAAiB2B,GACzCA,EAAYoD,SAUXpD,EAAYqD,MAUNrD,EAAYsD,aAUhCC,EAAAA,EAAAA,qBAAoBvD,EAAYoD,SAAUpD,EAAYqD,MAAOrD,EAAYsD,aARvE3E,QAAQa,MACN,gCAAwC,OAARnB,EAAQ,6JAExC2B,GAbFrB,QAAQa,MACN,gCAAwC,OAARnB,EAAQ,uJAExC2B,GAbFrB,QAAQa,MACN,gCAAwC,OAARnB,EAAQ,+IAExC2B,EA0BN,CCnFQwD,CAAuBnF,EAAS2B,GAEhCrB,QAAQC,KACN,sBAA8B,OAARP,EAAQ,kFAC9B2B,EAGN,GACF,CACF,CAUO,SAASyD,IACdvD,EAAMwD,MAAK,SAACC,EAAGC,GACb,IAAIF,EAAOC,EAAEhE,MAAQiE,EAAEjE,MACvB,OAAY,GAAR+D,EACKA,EAEFC,EAAEtF,QAAQwF,cAAcD,EAAEvF,QAAS,KAC5C,IAKA,IAAIyF,EAAa,IAAI3F,IAChB,mB,IAAL,QAAK,IAAY+B,EAAAA,OAAAA,cAAZ,0BAAmB,CAAnB,IAAI6D,EAAJ,QACED,EAAWE,IAAID,EAAK1F,SAGvByF,EAAWG,IAAIF,EAAK1F,QAASyF,EAAW7G,IAAI8G,EAAK1F,SAAW,GAF5DyF,EAAWG,IAAIF,EAAK1F,QAAS,GAI/B,IAAM6F,EAAQJ,EAAW7G,IAAI8G,EAAK1F,SAE5Bc,EAAO,GAAwB+E,OAArBH,EAAK1F,QAAQ,UAAc,OAAN6F,GAC/BC,EAAMC,SAASC,cAAc,OACnCF,EAAIG,GAAK,0BAA+B,OAALnF,GACnCiF,SAASG,KAAKC,YAAYL,GAC1BM,EAAgBtF,EAAM4E,EACxB,C,UAbK,Q,aAAA,6B,YAAA,E,MAAA,C,EAcP,CAUA,SAASU,EAAgBpG,EAAiB0F,GACxC,IAAM3D,OACkB,IAAf2D,EAAK3D,MACR2D,EAAK3D,WACsB,IAApB2D,EAAK3C,YACV,IAAIL,OAAOgD,EAAK3C,YAGxB,IAAc,IAAVhB,EASJ,GAAK2D,EAAKzF,UAAV,CASA,IAAMoG,EA1LR,SACEA,EACA,G,IAAE5E,EAAF,EAAEA,OAAQC,EAAV,EAAUA,QAASC,EAAnB,EAAmBA,YAEnB,OAAIa,OAAO8D,eACF,SAAClE,GAIN,SAAOmE,UAAUC,SAAW/E,SAAAA,KAAsB8E,UAAUC,QAAW9E,SAAAA,MAInEC,KACG8E,EAAAA,EAAAA,gBAAe9E,KAKf0E,EAAWjE,EACpB,EAEOiE,CAEX,CAkKqBK,CAAmB5E,EAAcC,GAAQ2D,GACtDxE,EAASnB,EAAU2F,EAAK1F,QAAS0F,EAAKzF,YAC5C0G,EAAAA,EAAAA,qBAAoB3G,EAASkB,EAAQmF,EAJrC,MANE/F,QAAQC,KACL,4KAEDP,QAZFM,QAAQC,KACL,6MAEDP,EAiBN,CClPuC,iB,yFAKvC,IAAM4G,GAAYC,E,OAAAA,oBAYX,SAASC,EAAkBvF,EAAoB0B,GACpD,GAAK2D,EAAL,CAIA,GAAsB,iBAAX3D,EAAqB,CAC9B,GAAIA,EAAO8D,WAAW,QACpB,OAAOC,EAAyBzF,EAAY0B,GAE5C,IACE,IAAMgE,EAAcC,KAAKC,MAAMlE,GAC/B,GAAImE,EAAmBH,GACrB,OAAOD,EAAyBzF,EAAY0F,GAE5C3G,QAAQa,MAAM,2BAAsC,OAAXI,EAAW,2CAA0C0B,EAElG,CAAE,MAAOoE,GACP/G,QAAQa,MAAM,qCAAgD,OAAXI,EAAW,MAAK8F,EACrE,CAEJ,KAAO,I,EAAIpE,E,SAAkBqE,M,0FAC3B,OAAON,EAAyBzF,EAAY0B,EAAOsE,YAC9C,GAAIH,EAAmBnE,GAC5B,OAAO+D,EAAyBzF,EAAY0B,EAC9C,C,QAEA3C,QAAQa,MACN,gBAA2B,OAAXI,EAAW,kHAC3B0B,EAzBF,CA2BF,CASO,SAASuE,EAAqBjG,GACnC,GAAKqF,EAAL,CAIA,IAAMrI,EAAMe,EAA2BiC,EACvCkG,aAAaC,WAAWnJ,EAHxB,CAIF,CAQO,SAASoJ,IACd,GAAKf,EAKL,IADA,IAAMa,EAAejF,OAAOiF,aACnBG,EAAI,EAAGA,EAAIH,EAAaI,OAAQD,IAAK,CAC5C,IAAMrJ,EAAMkJ,EAAalJ,IAAIqJ,IACzBrJ,aAAAA,EAAAA,EAAKwI,WAAWzH,KAClBmI,EAAaC,WAAWnJ,EAE5B,CACF,CAEA,SAASyI,EAAyBzF,EAAoB0B,GACpD,IAAM1E,EAAMe,EAA2BiC,EACvCkG,aAAaK,QAAQvJ,EAAK2I,KAAKa,UAAU9E,GAC3C,CAUO,SAASmE,EAAmBnE,GACjC,GAAIA,GAA4B,iBAAXA,EAAqB,CACxC,IAAMjE,EAAiBP,OAAOM,UAAUC,eAGlCiI,EAAchE,EAEpB,WAAIjE,EAAeC,KAAKgE,EAAQ,UACzB+E,QAAQf,EAAYpF,QAAWG,MAAMC,QAAQgF,EAAYpF,WAK5D7C,EAAeC,KAAKgE,EAAQ,eACzB+E,QAAQf,EAAY7D,aAAgBpB,MAAMC,QAAQgF,EAAY7D,gBAKjEpE,EAAeC,KAAKgE,EAAQ,eACzB+E,QAAQf,EAAYzD,aAAgBxB,MAAMC,QAAQgF,EAAYzD,gBAKjExE,EAAeC,KAAKgE,EAAQ,WACzB+E,QAAQf,EAAY3D,SAAYtB,MAAMC,QAAQgF,EAAY3D,SAQnE,CAEA,OAAO,CACT,CAUO,SAAS2E,EAAgBhF,GAC9B,GAAIA,GAA4B,iBAAXA,EAAqB,CACxC,IAAMgE,EAAchE,EAEpB,OAAOxE,OAAOyJ,QAAQjB,GAAakB,OAAM,Y,g1BAAE5J,EAAAA,EAAAA,GAAKc,EAAAA,EAAAA,G,MAA0B,iBAARd,GAAoB6I,EAAmB/H,E,GAC3G,CAEA,OAAO,CACT,C","sources":["webpack://@openmrs/esm-routes/external system \"@openmrs/esm-config\"","webpack://@openmrs/esm-routes/external system \"@openmrs/esm-dynamic-loading\"","webpack://@openmrs/esm-routes/external system \"@openmrs/esm-extensions\"","webpack://@openmrs/esm-routes/external system \"@openmrs/esm-feature-flags\"","webpack://@openmrs/esm-routes/external system \"@openmrs/esm-utils\"","webpack://@openmrs/esm-routes/external system \"single-spa\"","webpack://@openmrs/esm-routes/webpack/bootstrap","webpack://@openmrs/esm-routes/webpack/runtime/define property getters","webpack://@openmrs/esm-routes/webpack/runtime/hasOwnProperty shorthand","webpack://@openmrs/esm-routes/webpack/runtime/make namespace object","webpack://@openmrs/esm-routes/./src/constants.ts","webpack://@openmrs/esm-routes/./src/loaders/helpers.ts","webpack://@openmrs/esm-routes/./src/loaders/app.ts","webpack://@openmrs/esm-routes/./src/loaders/components.ts","webpack://@openmrs/esm-routes/./src/loaders/pages.ts","webpack://@openmrs/esm-routes/./src/routes.ts"],"sourcesContent":["module.exports = __WEBPACK_EXTERNAL_MODULE__824__;","module.exports = __WEBPACK_EXTERNAL_MODULE__758__;","module.exports = __WEBPACK_EXTERNAL_MODULE__45__;","module.exports = __WEBPACK_EXTERNAL_MODULE__708__;","module.exports = __WEBPACK_EXTERNAL_MODULE__618__;","module.exports = __WEBPACK_EXTERNAL_MODULE__645__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export const localStorageRoutesPrefix = 'openmrs-routes:';\n","import { type LifeCycles } from 'single-spa';\n\nexport const emptyLifecycle: LifeCycles<never> = {\n bootstrap() {\n return Promise.resolve();\n },\n mount() {\n return Promise.resolve();\n },\n unmount() {\n return Promise.resolve();\n },\n};\n\nexport function routeRegex(regex: RegExp, location: Location) {\n const result = regex.test(location.pathname.replace(window.getOpenmrsSpaBase(), ''));\n return result;\n}\n","import { importDynamic } from '@openmrs/esm-dynamic-loading';\nimport { type LifeCycles } from 'single-spa';\nimport { emptyLifecycle } from './helpers';\n\n// Couldn't figure out how to express this as an interface\ntype Module = Omit<Record<string, () => LifeCycles | Promise<LifeCycles>>, 'startupApp'> & {\n startupApp?: () => unknown;\n};\n\n/**\n * @internal\n *\n * Used internally to track which apps have had their `startupApp()` initializer called\n *\n * Values are promises to support asynchronous loading of the same app multiple times\n */\nconst initializedApps = new Map<string, Promise<unknown>>();\n\n/**\n * This function creates a loader function suitable for use in either a single-spa\n * application or parcel.\n *\n * The returned function is lazy and ensures that the appropriate module is loaded,\n * that the module's `startupApp()` is called before the component is loaded. It\n * then calls the component function, which should return either a single-spa\n * {@link LifeCycles} object or a {@link Promise} that will resolve to such an object.\n *\n * React-based pages or extensions should generally use the framework's\n * `getAsyncLifecycle()` or `getSyncLifecycle()` functions.\n */\nexport function getLoader(appName: string, component: string): () => Promise<LifeCycles> {\n return async () => {\n const module = await importDynamic<Module>(appName);\n\n if (module && Object.hasOwn(module, component) && typeof module[component] === 'function') {\n return initializeApp(appName, module).then(() => module[component]());\n } else {\n if (module && Object.hasOwn(module, component)) {\n console.warn(`The export ${component} of the app ${appName} is not a function`);\n } else {\n console.warn(`The app ${appName} does not define a component called ${component}, this cannot be loaded`);\n }\n }\n\n return emptyLifecycle;\n };\n}\n\n/**\n * This function can be used to manually initialize an application without waiting for the\n * framework to load it. This can sometimes be helpful if the framework doesn't load code\n * at the point you think is appropriate.\n *\n * This will ensure that the module is available and that it's `startupApp()` function (if\n * any) will be called. Note that these are only guaranteed to be complete once the Promise\n * returned from the function completes.\n *\n * @param appName The name of the app to initialize\n * @param module The loaded code module, if available; if this parameter is omitted, this\n * function will load it.\n * @returns a Promise which completes once the app has been loaded and initialized\n */\nexport async function initializeApp(appName: string, module?: Module) {\n if (!(appName in initializedApps)) {\n let _module: Module = module ?? (await importDynamic<Module>(appName));\n\n await (initializedApps[appName] = new Promise((resolve, reject) => {\n if (Object.hasOwn(_module, 'startupApp')) {\n const startup = _module['startupApp'];\n if (typeof startup === 'function') {\n return Promise.resolve(startup()).then(resolve).catch(reject);\n }\n }\n\n resolve(null);\n }));\n } else {\n await initializedApps[appName];\n }\n}\n","import {\n attach,\n type ExtensionRegistration,\n registerExtension,\n registerModal,\n registerWorkspace,\n} from '@openmrs/esm-extensions';\nimport {\n type FeatureFlagDefinition,\n type ExtensionDefinition,\n type ModalDefinition,\n type WorkspaceDefinition,\n} from '@openmrs/esm-globals';\nimport { getLoader } from './app';\nimport { FeatureFlag, registerFeatureFlag } from '@openmrs/esm-feature-flags';\n\n/**\n * This function registers an extension definition with the framework and will\n * attach the extension to any configured slots.\n *\n * @param appName The name of the app containing this extension\n * @param extension An object that describes the extension, derived from `routes.json`\n */\nexport function tryRegisterExtension(appName: string, extension: ExtensionDefinition) {\n const name = extension.name;\n if (!name) {\n console.error(\n `An extension definition in ${appName} is missing an name and thus cannot be\nregistered. To fix this, ensure that you define the \"name\" field inside the\nextension definition.`,\n extension,\n );\n return;\n }\n\n if (extension.slots && extension.slot) {\n console.warn(\n `The extension ${name} from ${appName} declares both a 'slots' property and\na 'slot' property. Only the 'slots' property will be honored.`,\n );\n }\n const slots = extension.slots ? extension.slots : extension.slot ? [extension.slot] : [];\n\n if (!extension.component && !extension.load) {\n console.error(\n `The extension ${name} from ${appName} is missing a 'component' entry and thus cannot be registered.\nTo fix this, ensure that you define a 'component' field inside the extension definition.`,\n extension,\n );\n return;\n }\n\n let loader: ExtensionRegistration['load'] | undefined = undefined;\n if (extension.component) {\n loader = getLoader(appName, extension.component);\n } else if (extension.load) {\n if (typeof extension.load !== 'function') {\n console.error(\n `The extension ${name} from ${appName} declares a 'load' property that is not a function. This is not\nsupported, so the extension will not be loaded.`,\n );\n return;\n }\n loader = extension.load;\n }\n\n if (loader) {\n registerExtension({\n name,\n load: loader,\n meta: extension.meta || {},\n order: extension.order,\n moduleName: appName,\n privileges: extension.privileges,\n online: extension.online ?? true,\n offline: extension.offline ?? false,\n featureFlag: extension.featureFlag,\n });\n }\n\n for (const slot of slots) {\n attach(slot, name);\n }\n}\n\n/**\n * This function registers a modal definition with the framework so that it can be launched.\n *\n * @param appName The name of the app defining this modal\n * @param modal An object that describes the modal, derived from `routes.json`\n */\nexport function tryRegisterModal(appName: string, modal: ModalDefinition) {\n const name = modal.name;\n if (!name) {\n console.error(\n `A modal definition in ${appName} is missing an name and thus cannot be\nregistered. To fix this, ensure that you define the \"name\" field inside the\nmodal definition.`,\n modal,\n );\n return;\n }\n\n if (!modal.component && !modal.load) {\n console.error(\n `The modal ${name} from ${appName} is missing a 'component' entry and thus cannot be registered.\nTo fix this, ensure that you define a 'component' field inside the modal definition.`,\n modal,\n );\n return;\n }\n\n let loader: ExtensionRegistration['load'] | undefined = undefined;\n if (modal.component) {\n loader = getLoader(appName, modal.component);\n } else if (modal.load) {\n if (typeof modal.load !== 'function') {\n console.error(\n `The modal ${name} from ${appName} declares a 'load' property that is not a function. This is not\nsupported, so the modal will not be loaded.`,\n );\n return;\n }\n loader = modal.load;\n }\n\n if (loader) {\n registerModal({\n name,\n load: loader,\n moduleName: appName,\n });\n }\n}\n\n/**\n * This function registers a workspace definition with the framework so that it can be launched.\n *\n * @param appName The name of the app defining this workspace\n * @param workspace An object that describes the workspace, derived from `routes.json`\n */\nexport function tryRegisterWorkspace(appName: string, workspace: WorkspaceDefinition) {\n const name = workspace.name;\n if (!name) {\n console.error(\n `A workspace definition in ${appName} is missing a name and thus cannot be registered.\nTo fix this, ensure that you define the \"name\" field inside the workspace definition.`,\n workspace,\n );\n return;\n }\n\n const title = workspace.title;\n if (!title) {\n console.error(\n `A workspace definition in ${appName} is missing a title and thus cannot be registered.\nTo fix this, ensure that you define the \"title\" field inside the workspace definition.`,\n workspace,\n );\n return;\n }\n\n if (!workspace.component && !workspace.load) {\n console.error(\n `The workspace ${name} from ${appName} is missing a 'component' entry and thus cannot be registered.\nTo fix this, ensure that you define a 'component' field inside the workspace definition.`,\n workspace,\n );\n return;\n }\n\n let loader: ExtensionRegistration['load'] | undefined = undefined;\n if (workspace.component) {\n loader = getLoader(appName, workspace.component);\n } else if (workspace.load) {\n if (typeof workspace.load !== 'function') {\n console.error(\n `The workspace ${name} from ${appName} declares a 'load' property that is not a function. This is not\nsupported, so the workspace will not be loaded.`,\n );\n return;\n }\n loader = workspace.load;\n }\n\n if (loader) {\n registerWorkspace({\n name,\n title,\n load: loader,\n moduleName: appName,\n type: workspace.type,\n canHide: workspace.canHide,\n canMaximize: workspace.canMaximize,\n width: workspace.width,\n hasOwnSidebar: workspace.hasOwnSidebar,\n sidebarFamily: workspace.sidebarFamily,\n preferredWindowSize: workspace.preferredWindowSize,\n });\n }\n}\n\n/**\n * This function registers a workspace definition with the framework so that it can be launched.\n *\n * @param appName The name of the app defining this workspace\n * @param workspace An object that describes the workspace, derived from `routes.json`\n */\nexport function tryRegisterFeatureFlag(appName: string, featureFlag: FeatureFlagDefinition) {\n const name = featureFlag.flagName;\n if (!name) {\n console.error(\n `A feature flag definition in ${appName} is missing a name and thus cannot be registered.\nTo fix this, ensure that you define the \"name\" field inside the feature flag definition.`,\n featureFlag,\n );\n return;\n }\n\n const label = featureFlag.label;\n if (!label) {\n console.error(\n `A feature flag definition in ${appName} is missing a description and thus cannot be registered.\nTo fix this, ensure that you define the \"label\" field inside the feature flag definition.`,\n featureFlag,\n );\n return;\n }\n\n const description = featureFlag.description;\n if (!description) {\n console.error(\n `A feature flag definition in ${appName} is missing a description and thus cannot be registered.\nTo fix this, ensure that you define the \"description\" field inside the feature flag definition.`,\n featureFlag,\n );\n return;\n }\n\n registerFeatureFlag(featureFlag.flagName, featureFlag.label, featureFlag.description);\n}\n","import { type ActivityFn, pathToActiveWhen, registerApplication } from 'single-spa';\nimport { registerModuleWithConfigSystem } from '@openmrs/esm-config';\nimport {\n type ExtensionDefinition,\n type FeatureFlagDefinition,\n type ModalDefinition,\n type OpenmrsAppRoutes,\n type RegisteredPageDefinition,\n type RouteDefinition,\n type WorkspaceDefinition,\n} from '@openmrs/esm-globals';\nimport { getFeatureFlag } from '@openmrs/esm-feature-flags';\nimport { routeRegex } from './helpers';\nimport { getLoader } from './app';\nimport { tryRegisterExtension, tryRegisterFeatureFlag, tryRegisterModal, tryRegisterWorkspace } from './components';\n\n// this is the global holder of all pages registered in the app\nconst pages: Array<RegisteredPageDefinition> = [];\n\n/**\n * This takes a page's route definitions and returns a single-spa\n * activityFn which returns true when the page matches the current\n * route and false if it does not.\n *\n * @param route A string or regexp that matches the location when the\n * page should be displayed, a boolean constant, or an array of such\n * strings, regexps, and booleans\n * @returns An activityFn suitable to use for a single-spa application\n */\nfunction getActivityFn(route: RouteDefinition | Array<RouteDefinition>): ActivityFn {\n if (Array.isArray(route)) {\n const activators = route.map(getActivityFn);\n return (location) => activators.some((activator) => activator(location));\n } else if (typeof route === 'string') {\n return pathToActiveWhen(window.getOpenmrsSpaBase() + route);\n } else if (route instanceof RegExp) {\n return (location) => routeRegex(route, location);\n } else {\n return () => route;\n }\n}\n\n/**\n * For pages, we also add support for rendered them based on online and offline mode as well as\n * any feature flags.\n *\n * By default, we assume that all pages should be rendered when online, but only rendered\n * offline if specifically configured to do so.\n *\n * @param activityFn A standard single-spa activityFn such as that returned by {@link getActivityFn()}\n * @param pageDefinition The RegisteredPageDefinition object for this page\n * @returns An activityFn suitable to use for a single-spa application\n */\nfunction wrapPageActivityFn(\n activityFn: ActivityFn,\n { online, offline, featureFlag }: RegisteredPageDefinition,\n): ActivityFn {\n if (window.offlineEnabled) {\n return (location) => {\n // basically, if the page should only work online and we're offline or if the\n // page should only work offline and we're online, defaulting to always rendering\n // the page\n if (!((navigator.onLine && (online ?? true)) || (!navigator.onLine && (offline ?? false)))) {\n return false;\n }\n\n if (featureFlag) {\n if (!getFeatureFlag(featureFlag)) {\n return false;\n }\n }\n\n return activityFn(location);\n };\n } else {\n return activityFn;\n }\n}\n\n/**\n * This is the main entry-point for registering an app with the app shell.\n * Each app has a name and should have a `routes.json` file that defines it's\n * associated routes.\n *\n * @param appName The name of the application, e.g. `@openmrs/esm-my-app`\n * @param routes A Javascript object that corresponds to the app's routes.json`\n * definition.\n */\nexport function registerApp(appName: string, routes: OpenmrsAppRoutes) {\n if (appName && routes && typeof routes === 'object') {\n registerModuleWithConfigSystem(appName);\n\n const availableExtensions: Array<ExtensionDefinition> = routes.extensions ?? [];\n const availableModals: Array<ModalDefinition> = routes.modals ?? [];\n const availableWorkspaces: Array<WorkspaceDefinition> = routes.workspaces ?? [];\n const availableFeatureFlags: Array<FeatureFlagDefinition> = routes.featureFlags ?? [];\n\n routes.pages?.forEach((p) => {\n if (\n p &&\n typeof p === 'object' &&\n Object.hasOwn(p, 'component') &&\n (Object.hasOwn(p, 'route') || Object.hasOwn(p, 'routeRegex') || Object.hasOwn(p, 'routes'))\n ) {\n pages.push({\n ...p,\n order: p.order ?? Number.MAX_SAFE_INTEGER,\n appName,\n });\n } else {\n console.warn(\n `A page for ${appName} could not be registered as it does not appear to have the required properties`,\n p,\n );\n }\n });\n\n availableExtensions.forEach((ext) => {\n if (ext && typeof ext === 'object' && Object.hasOwn(ext, 'name') && Object.hasOwn(ext, 'component')) {\n tryRegisterExtension(appName, ext);\n } else {\n console.warn(\n `An extension for ${appName} could not be registered as it does not appear to have the required properties`,\n ext,\n );\n }\n });\n\n availableModals.forEach((modal) => {\n if (modal && typeof modal === 'object' && Object.hasOwn(modal, 'name') && Object.hasOwn(modal, 'component')) {\n tryRegisterModal(appName, modal);\n } else {\n console.warn(\n `A modal for ${appName} could not be registered as it does not appear to have the required properties`,\n modal,\n );\n }\n });\n\n availableWorkspaces.forEach((workspace) => {\n if (\n workspace &&\n typeof workspace === 'object' &&\n Object.hasOwn(workspace, 'name') &&\n Object.hasOwn(workspace, 'component')\n ) {\n tryRegisterWorkspace(appName, workspace);\n } else {\n console.warn(\n `A workspace for ${appName} could not be registered as it does not appear to have the required properties`,\n workspace,\n );\n }\n });\n\n availableFeatureFlags.forEach((featureFlag) => {\n if (featureFlag && typeof featureFlag === 'object' && Object.hasOwn(featureFlag, 'featureFlag')) {\n tryRegisterFeatureFlag(appName, featureFlag);\n } else {\n console.warn(\n `A feature flag for ${appName} could not be registered as it does not appear to have the required properties`,\n featureFlag,\n );\n }\n });\n }\n}\n\n/**\n * This is called by the app shell once all route entries have been processed.\n * This actually registers the pages with the application. This function is\n * necessary to ensure that pages are rendered in the DOM according to their\n * order definition, especially because certain pages _must_ be first in the DOM.\n *\n * Each page is rendered into a div with an appropriate name.\n */\nexport function finishRegisteringAllApps() {\n pages.sort((a, b) => {\n let sort = a.order - b.order;\n if (sort != 0) {\n return sort;\n }\n return a.appName.localeCompare(b.appName, 'en');\n });\n\n // Create a div for each page. This ensures their DOM order.\n // If we don't do this, Single-SPA 5 will create the DOM element only once\n // the page becomes active, which makes it impossible to guarantee order.\n let appIndices = new Map();\n for (let page of pages) {\n if (!appIndices.has(page.appName)) {\n appIndices.set(page.appName, 0);\n } else {\n appIndices.set(page.appName, appIndices.get(page.appName) + 1);\n }\n const index = appIndices.get(page.appName);\n\n const name = `${page.appName}-page-${index}`;\n const div = document.createElement('div');\n div.id = `single-spa-application:${name}`;\n document.body.appendChild(div);\n tryRegisterPage(name, page);\n }\n}\n\n/**\n * This function converts each page definition into a single-spa application\n * if that's possible. After this point, pages are rendered using single-spa's\n * routing logic.\n *\n * @param appName The name of the app containing this page\n * @param page An object that describes the page, derived from `routes.json`\n */\nfunction tryRegisterPage(appName: string, page: RegisteredPageDefinition) {\n const route =\n typeof page.route !== 'undefined'\n ? page.route\n : typeof page.routeRegex !== 'undefined'\n ? new RegExp(page.routeRegex)\n : false;\n\n if (route === false) {\n console.warn(\n `A registered page definition is missing a route and thus cannot be registered.\nTo fix this, ensure that you define the \"route\" (or alternatively the \"routeRegex\") field inside the extension definition.`,\n appName,\n );\n return;\n }\n\n if (!page.component) {\n console.warn(\n `A registered page definition is missing a component and thus cannot be registered.\nTo fix this, ensure that you define the \"component\" field inside the page definition.`,\n appName,\n );\n return;\n }\n\n const activityFn = wrapPageActivityFn(getActivityFn(route), page);\n const loader = getLoader(page.appName, page.component);\n registerApplication(appName, loader, activityFn);\n}\n","/** @module @category Routes Utilities */\nimport type { OpenmrsAppRoutes, OpenmrsRoutes } from '@openmrs/esm-globals';\nimport { canAccessStorage } from '@openmrs/esm-utils';\nimport { localStorageRoutesPrefix } from './constants';\n\nconst isEnabled = canAccessStorage();\n\n/**\n * Used to add a route override to local storage. These are read as the routes registry\n * is assembled, so the app must be reloaded for new overrides to take effect.\n *\n * @internal\n * @param moduleName The name of the module the routes are for\n * @param routes Either an {@link OpenmrsAppRoutes} object, a string that represents a JSON\n * version of an {@link OpenmrsAppRoutes} object or a string or URL that resolves to a\n * JSON document that represents an {@link OpenmrsAppRoutes} object\n */\nexport function addRoutesOverride(moduleName: string, routes: OpenmrsAppRoutes | string | URL) {\n if (!isEnabled) {\n return;\n }\n\n if (typeof routes === 'string') {\n if (routes.startsWith('http')) {\n return addRouteOverrideInternal(moduleName, routes);\n } else {\n try {\n const maybeRoutes = JSON.parse(routes);\n if (isOpenmrsAppRoutes(maybeRoutes)) {\n return addRouteOverrideInternal(moduleName, maybeRoutes);\n } else {\n console.error(`The supplied routes for ${moduleName} is not a valid OpenmrsAppRoutes object`, routes);\n }\n } catch (e) {\n console.error(`Could not add routes override for ${moduleName}: `, e);\n }\n }\n } else if (routes instanceof URL) {\n return addRouteOverrideInternal(moduleName, routes.toString());\n } else if (isOpenmrsAppRoutes(routes)) {\n return addRouteOverrideInternal(moduleName, routes);\n }\n\n console.error(\n `Override for ${moduleName} is not in a valid format. Expected either a Javascript Object, a JSON string of a Javascript object, or a URL`,\n routes,\n );\n}\n\n/**\n * Used to remove an existing routes override from local storage. These are read as the routes registry\n * is assembled, so the app must be reloaded for removed override to be removed.\n *\n * @internal\n * @param moduleName The module to remove the overrides for\n */\nexport function removeRoutesOverride(moduleName: string) {\n if (!isEnabled) {\n return;\n }\n\n const key = localStorageRoutesPrefix + moduleName;\n localStorage.removeItem(key);\n}\n\n/**\n * Used to remove all existing routes overrides from local storage. These are read as the routes registry\n * is assembled, so the app must be reloaded for the removed overrides to appear to be removed.\n *\n * @internal\n */\nexport function resetAllRoutesOverrides() {\n if (!isEnabled) {\n return;\n }\n\n const localStorage = window.localStorage;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(localStorageRoutesPrefix)) {\n localStorage.removeItem(key);\n }\n }\n}\n\nfunction addRouteOverrideInternal(moduleName: string, routes: OpenmrsAppRoutes | string) {\n const key = localStorageRoutesPrefix + moduleName;\n localStorage.setItem(key, JSON.stringify(routes));\n}\n\n/**\n * Simple type-predicate to ensure that the value can be treated as an OpenmrsAppRoutes\n * object.\n *\n * @internal\n * @param routes the object to check to see if it is an OpenmrsAppRoutes object\n * @returns true if the routes value is an OpenmrsAppRoutes\n */\nexport function isOpenmrsAppRoutes(routes: OpenmrsAppRoutes | unknown): routes is OpenmrsAppRoutes {\n if (routes && typeof routes === 'object') {\n const hasOwnProperty = Object.prototype.hasOwnProperty;\n // we cast maybeRoutes as OpenmrsAppRoutes mainly so we can refer to the properties it should\n // have without repeated casts\n const maybeRoutes = routes as OpenmrsAppRoutes;\n\n if (hasOwnProperty.call(routes, 'pages')) {\n if (!Boolean(maybeRoutes.pages) || !Array.isArray(maybeRoutes.pages)) {\n return false;\n }\n }\n\n if (hasOwnProperty.call(routes, 'extensions')) {\n if (!Boolean(maybeRoutes.extensions) || !Array.isArray(maybeRoutes.extensions)) {\n return false;\n }\n }\n\n if (hasOwnProperty.call(routes, 'workspaces')) {\n if (!Boolean(maybeRoutes.workspaces) || !Array.isArray(maybeRoutes.workspaces)) {\n return false;\n }\n }\n\n if (hasOwnProperty.call(routes, 'modals')) {\n if (!Boolean(maybeRoutes.modals) || !Array.isArray(maybeRoutes.modals)) {\n return false;\n }\n }\n\n // Notice that we're essentially testing for things that cannot be treated as an OpenmrsAppRoutes\n // object. This is because a completely empty object is a valid OpenmrsAppRoutes object.\n return true;\n }\n\n return false;\n}\n\n/**\n * Simple type-predicate to ensure that the value can be treated as an OpenmrsRoutes\n * object.\n *\n * @internal\n * @param routes the object to check to see if it is an OpenmrsRoutes object\n * @returns true if the routes value is an OpenmrsRoutes\n */\nexport function isOpenmrsRoutes(routes: OpenmrsRoutes | unknown): routes is OpenmrsRoutes {\n if (routes && typeof routes === 'object') {\n const maybeRoutes = routes as OpenmrsRoutes;\n\n return Object.entries(maybeRoutes).every(([key, value]) => typeof key === 'string' && isOpenmrsAppRoutes(value));\n }\n\n return false;\n}\n"],"names":["module","exports","__WEBPACK_EXTERNAL_MODULE__824__","__WEBPACK_EXTERNAL_MODULE__758__","__WEBPACK_EXTERNAL_MODULE__45__","__WEBPACK_EXTERNAL_MODULE__708__","__WEBPACK_EXTERNAL_MODULE__618__","__WEBPACK_EXTERNAL_MODULE__645__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","d","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag","value","localStorageRoutesPrefix","emptyLifecycle","bootstrap","Promise","resolve","mount","unmount","initializedApps","Map","getLoader","appName","component","importDynamic","hasOwn","initializeApp","then","console","warn","_module","reject","startup","catch","tryRegisterExtension","extension","name","slots","slot","load","loader","error","registerExtension","meta","order","moduleName","privileges","online","offline","featureFlag","attach","pages","getActivityFn","route","Array","isArray","activators","map","location","some","activator","pathToActiveWhen","window","getOpenmrsSpaBase","RegExp","regex","test","pathname","replace","routeRegex","registerApp","routes","registerModuleWithConfigSystem","availableExtensions","extensions","availableModals","modals","availableWorkspaces","workspaces","availableFeatureFlags","featureFlags","forEach","p","push","Number","MAX_SAFE_INTEGER","ext","modal","registerModal","tryRegisterModal","workspace","title","registerWorkspace","type","canHide","canMaximize","width","hasOwnSidebar","sidebarFamily","preferredWindowSize","tryRegisterWorkspace","flagName","label","description","registerFeatureFlag","tryRegisterFeatureFlag","finishRegisteringAllApps","sort","a","b","localeCompare","appIndices","page","has","set","index","div","document","createElement","id","body","appendChild","tryRegisterPage","activityFn","offlineEnabled","navigator","onLine","getFeatureFlag","wrapPageActivityFn","registerApplication","isEnabled","canAccessStorage","addRoutesOverride","startsWith","addRouteOverrideInternal","maybeRoutes","JSON","parse","isOpenmrsAppRoutes","e","URL","toString","removeRoutesOverride","localStorage","removeItem","resetAllRoutesOverrides","i","length","setItem","stringify","Boolean","isOpenmrsRoutes","entries","every"],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-routes",
3
- "version": "5.7.2",
3
+ "version": "5.7.3-pre.2113",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Utilities for working with the routes registry",
6
6
  "browser": "dist/openmrs-esm-routes.js",
@@ -39,12 +39,23 @@
39
39
  "access": "public"
40
40
  },
41
41
  "peerDependencies": {
42
+ "@openmrs/esm-config": "5.x",
43
+ "@openmrs/esm-dynamic-loading": "5.x",
44
+ "@openmrs/esm-extensions": "5.x",
45
+ "@openmrs/esm-feature-flags": "5.x",
42
46
  "@openmrs/esm-globals": "5.x",
43
- "@openmrs/esm-utils": "5.x"
47
+ "@openmrs/esm-utils": "5.x",
48
+ "single-spa": "6.x"
44
49
  },
45
50
  "devDependencies": {
46
- "@openmrs/esm-globals": "5.7.2",
47
- "@openmrs/esm-utils": "5.7.2",
48
- "jest-fetch-mock": "^3.0.3"
49
- }
51
+ "@openmrs/esm-config": "5.7.3-pre.2113",
52
+ "@openmrs/esm-dynamic-loading": "5.7.3-pre.2113",
53
+ "@openmrs/esm-extensions": "5.7.3-pre.2113",
54
+ "@openmrs/esm-feature-flags": "5.7.3-pre.2113",
55
+ "@openmrs/esm-globals": "5.7.3-pre.2113",
56
+ "@openmrs/esm-utils": "5.7.3-pre.2113",
57
+ "jest-fetch-mock": "^3.0.3",
58
+ "single-spa": "^6.0.1"
59
+ },
60
+ "stableVersion": "5.7.2"
50
61
  }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './constants';
2
+ export * from './loaders';
2
3
  export * from './routes';
@@ -0,0 +1,80 @@
1
+ import { importDynamic } from '@openmrs/esm-dynamic-loading';
2
+ import { type LifeCycles } from 'single-spa';
3
+ import { emptyLifecycle } from './helpers';
4
+
5
+ // Couldn't figure out how to express this as an interface
6
+ type Module = Omit<Record<string, () => LifeCycles | Promise<LifeCycles>>, 'startupApp'> & {
7
+ startupApp?: () => unknown;
8
+ };
9
+
10
+ /**
11
+ * @internal
12
+ *
13
+ * Used internally to track which apps have had their `startupApp()` initializer called
14
+ *
15
+ * Values are promises to support asynchronous loading of the same app multiple times
16
+ */
17
+ const initializedApps = new Map<string, Promise<unknown>>();
18
+
19
+ /**
20
+ * This function creates a loader function suitable for use in either a single-spa
21
+ * application or parcel.
22
+ *
23
+ * The returned function is lazy and ensures that the appropriate module is loaded,
24
+ * that the module's `startupApp()` is called before the component is loaded. It
25
+ * then calls the component function, which should return either a single-spa
26
+ * {@link LifeCycles} object or a {@link Promise} that will resolve to such an object.
27
+ *
28
+ * React-based pages or extensions should generally use the framework's
29
+ * `getAsyncLifecycle()` or `getSyncLifecycle()` functions.
30
+ */
31
+ export function getLoader(appName: string, component: string): () => Promise<LifeCycles> {
32
+ return async () => {
33
+ const module = await importDynamic<Module>(appName);
34
+
35
+ if (module && Object.hasOwn(module, component) && typeof module[component] === 'function') {
36
+ return initializeApp(appName, module).then(() => module[component]());
37
+ } else {
38
+ if (module && Object.hasOwn(module, component)) {
39
+ console.warn(`The export ${component} of the app ${appName} is not a function`);
40
+ } else {
41
+ console.warn(`The app ${appName} does not define a component called ${component}, this cannot be loaded`);
42
+ }
43
+ }
44
+
45
+ return emptyLifecycle;
46
+ };
47
+ }
48
+
49
+ /**
50
+ * This function can be used to manually initialize an application without waiting for the
51
+ * framework to load it. This can sometimes be helpful if the framework doesn't load code
52
+ * at the point you think is appropriate.
53
+ *
54
+ * This will ensure that the module is available and that it's `startupApp()` function (if
55
+ * any) will be called. Note that these are only guaranteed to be complete once the Promise
56
+ * returned from the function completes.
57
+ *
58
+ * @param appName The name of the app to initialize
59
+ * @param module The loaded code module, if available; if this parameter is omitted, this
60
+ * function will load it.
61
+ * @returns a Promise which completes once the app has been loaded and initialized
62
+ */
63
+ export async function initializeApp(appName: string, module?: Module) {
64
+ if (!(appName in initializedApps)) {
65
+ let _module: Module = module ?? (await importDynamic<Module>(appName));
66
+
67
+ await (initializedApps[appName] = new Promise((resolve, reject) => {
68
+ if (Object.hasOwn(_module, 'startupApp')) {
69
+ const startup = _module['startupApp'];
70
+ if (typeof startup === 'function') {
71
+ return Promise.resolve(startup()).then(resolve).catch(reject);
72
+ }
73
+ }
74
+
75
+ resolve(null);
76
+ }));
77
+ } else {
78
+ await initializedApps[appName];
79
+ }
80
+ }
@@ -0,0 +1,241 @@
1
+ import {
2
+ attach,
3
+ type ExtensionRegistration,
4
+ registerExtension,
5
+ registerModal,
6
+ registerWorkspace,
7
+ } from '@openmrs/esm-extensions';
8
+ import {
9
+ type FeatureFlagDefinition,
10
+ type ExtensionDefinition,
11
+ type ModalDefinition,
12
+ type WorkspaceDefinition,
13
+ } from '@openmrs/esm-globals';
14
+ import { getLoader } from './app';
15
+ import { FeatureFlag, registerFeatureFlag } from '@openmrs/esm-feature-flags';
16
+
17
+ /**
18
+ * This function registers an extension definition with the framework and will
19
+ * attach the extension to any configured slots.
20
+ *
21
+ * @param appName The name of the app containing this extension
22
+ * @param extension An object that describes the extension, derived from `routes.json`
23
+ */
24
+ export function tryRegisterExtension(appName: string, extension: ExtensionDefinition) {
25
+ const name = extension.name;
26
+ if (!name) {
27
+ console.error(
28
+ `An extension definition in ${appName} is missing an name and thus cannot be
29
+ registered. To fix this, ensure that you define the "name" field inside the
30
+ extension definition.`,
31
+ extension,
32
+ );
33
+ return;
34
+ }
35
+
36
+ if (extension.slots && extension.slot) {
37
+ console.warn(
38
+ `The extension ${name} from ${appName} declares both a 'slots' property and
39
+ a 'slot' property. Only the 'slots' property will be honored.`,
40
+ );
41
+ }
42
+ const slots = extension.slots ? extension.slots : extension.slot ? [extension.slot] : [];
43
+
44
+ if (!extension.component && !extension.load) {
45
+ console.error(
46
+ `The extension ${name} from ${appName} is missing a 'component' entry and thus cannot be registered.
47
+ To fix this, ensure that you define a 'component' field inside the extension definition.`,
48
+ extension,
49
+ );
50
+ return;
51
+ }
52
+
53
+ let loader: ExtensionRegistration['load'] | undefined = undefined;
54
+ if (extension.component) {
55
+ loader = getLoader(appName, extension.component);
56
+ } else if (extension.load) {
57
+ if (typeof extension.load !== 'function') {
58
+ console.error(
59
+ `The extension ${name} from ${appName} declares a 'load' property that is not a function. This is not
60
+ supported, so the extension will not be loaded.`,
61
+ );
62
+ return;
63
+ }
64
+ loader = extension.load;
65
+ }
66
+
67
+ if (loader) {
68
+ registerExtension({
69
+ name,
70
+ load: loader,
71
+ meta: extension.meta || {},
72
+ order: extension.order,
73
+ moduleName: appName,
74
+ privileges: extension.privileges,
75
+ online: extension.online ?? true,
76
+ offline: extension.offline ?? false,
77
+ featureFlag: extension.featureFlag,
78
+ });
79
+ }
80
+
81
+ for (const slot of slots) {
82
+ attach(slot, name);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * This function registers a modal definition with the framework so that it can be launched.
88
+ *
89
+ * @param appName The name of the app defining this modal
90
+ * @param modal An object that describes the modal, derived from `routes.json`
91
+ */
92
+ export function tryRegisterModal(appName: string, modal: ModalDefinition) {
93
+ const name = modal.name;
94
+ if (!name) {
95
+ console.error(
96
+ `A modal definition in ${appName} is missing an name and thus cannot be
97
+ registered. To fix this, ensure that you define the "name" field inside the
98
+ modal definition.`,
99
+ modal,
100
+ );
101
+ return;
102
+ }
103
+
104
+ if (!modal.component && !modal.load) {
105
+ console.error(
106
+ `The modal ${name} from ${appName} is missing a 'component' entry and thus cannot be registered.
107
+ To fix this, ensure that you define a 'component' field inside the modal definition.`,
108
+ modal,
109
+ );
110
+ return;
111
+ }
112
+
113
+ let loader: ExtensionRegistration['load'] | undefined = undefined;
114
+ if (modal.component) {
115
+ loader = getLoader(appName, modal.component);
116
+ } else if (modal.load) {
117
+ if (typeof modal.load !== 'function') {
118
+ console.error(
119
+ `The modal ${name} from ${appName} declares a 'load' property that is not a function. This is not
120
+ supported, so the modal will not be loaded.`,
121
+ );
122
+ return;
123
+ }
124
+ loader = modal.load;
125
+ }
126
+
127
+ if (loader) {
128
+ registerModal({
129
+ name,
130
+ load: loader,
131
+ moduleName: appName,
132
+ });
133
+ }
134
+ }
135
+
136
+ /**
137
+ * This function registers a workspace definition with the framework so that it can be launched.
138
+ *
139
+ * @param appName The name of the app defining this workspace
140
+ * @param workspace An object that describes the workspace, derived from `routes.json`
141
+ */
142
+ export function tryRegisterWorkspace(appName: string, workspace: WorkspaceDefinition) {
143
+ const name = workspace.name;
144
+ if (!name) {
145
+ console.error(
146
+ `A workspace definition in ${appName} is missing a name and thus cannot be registered.
147
+ To fix this, ensure that you define the "name" field inside the workspace definition.`,
148
+ workspace,
149
+ );
150
+ return;
151
+ }
152
+
153
+ const title = workspace.title;
154
+ if (!title) {
155
+ console.error(
156
+ `A workspace definition in ${appName} is missing a title and thus cannot be registered.
157
+ To fix this, ensure that you define the "title" field inside the workspace definition.`,
158
+ workspace,
159
+ );
160
+ return;
161
+ }
162
+
163
+ if (!workspace.component && !workspace.load) {
164
+ console.error(
165
+ `The workspace ${name} from ${appName} is missing a 'component' entry and thus cannot be registered.
166
+ To fix this, ensure that you define a 'component' field inside the workspace definition.`,
167
+ workspace,
168
+ );
169
+ return;
170
+ }
171
+
172
+ let loader: ExtensionRegistration['load'] | undefined = undefined;
173
+ if (workspace.component) {
174
+ loader = getLoader(appName, workspace.component);
175
+ } else if (workspace.load) {
176
+ if (typeof workspace.load !== 'function') {
177
+ console.error(
178
+ `The workspace ${name} from ${appName} declares a 'load' property that is not a function. This is not
179
+ supported, so the workspace will not be loaded.`,
180
+ );
181
+ return;
182
+ }
183
+ loader = workspace.load;
184
+ }
185
+
186
+ if (loader) {
187
+ registerWorkspace({
188
+ name,
189
+ title,
190
+ load: loader,
191
+ moduleName: appName,
192
+ type: workspace.type,
193
+ canHide: workspace.canHide,
194
+ canMaximize: workspace.canMaximize,
195
+ width: workspace.width,
196
+ hasOwnSidebar: workspace.hasOwnSidebar,
197
+ sidebarFamily: workspace.sidebarFamily,
198
+ preferredWindowSize: workspace.preferredWindowSize,
199
+ });
200
+ }
201
+ }
202
+
203
+ /**
204
+ * This function registers a workspace definition with the framework so that it can be launched.
205
+ *
206
+ * @param appName The name of the app defining this workspace
207
+ * @param workspace An object that describes the workspace, derived from `routes.json`
208
+ */
209
+ export function tryRegisterFeatureFlag(appName: string, featureFlag: FeatureFlagDefinition) {
210
+ const name = featureFlag.flagName;
211
+ if (!name) {
212
+ console.error(
213
+ `A feature flag definition in ${appName} is missing a name and thus cannot be registered.
214
+ To fix this, ensure that you define the "name" field inside the feature flag definition.`,
215
+ featureFlag,
216
+ );
217
+ return;
218
+ }
219
+
220
+ const label = featureFlag.label;
221
+ if (!label) {
222
+ console.error(
223
+ `A feature flag definition in ${appName} is missing a description and thus cannot be registered.
224
+ To fix this, ensure that you define the "label" field inside the feature flag definition.`,
225
+ featureFlag,
226
+ );
227
+ return;
228
+ }
229
+
230
+ const description = featureFlag.description;
231
+ if (!description) {
232
+ console.error(
233
+ `A feature flag definition in ${appName} is missing a description and thus cannot be registered.
234
+ To fix this, ensure that you define the "description" field inside the feature flag definition.`,
235
+ featureFlag,
236
+ );
237
+ return;
238
+ }
239
+
240
+ registerFeatureFlag(featureFlag.flagName, featureFlag.label, featureFlag.description);
241
+ }
@@ -0,0 +1,18 @@
1
+ import { type LifeCycles } from 'single-spa';
2
+
3
+ export const emptyLifecycle: LifeCycles<never> = {
4
+ bootstrap() {
5
+ return Promise.resolve();
6
+ },
7
+ mount() {
8
+ return Promise.resolve();
9
+ },
10
+ unmount() {
11
+ return Promise.resolve();
12
+ },
13
+ };
14
+
15
+ export function routeRegex(regex: RegExp, location: Location) {
16
+ const result = regex.test(location.pathname.replace(window.getOpenmrsSpaBase(), ''));
17
+ return result;
18
+ }
@@ -0,0 +1,3 @@
1
+ export { initializeApp } from './app';
2
+ export { registerApp, finishRegisteringAllApps } from './pages';
3
+ export { tryRegisterExtension } from './components';
@@ -0,0 +1,243 @@
1
+ import { type ActivityFn, pathToActiveWhen, registerApplication } from 'single-spa';
2
+ import { registerModuleWithConfigSystem } from '@openmrs/esm-config';
3
+ import {
4
+ type ExtensionDefinition,
5
+ type FeatureFlagDefinition,
6
+ type ModalDefinition,
7
+ type OpenmrsAppRoutes,
8
+ type RegisteredPageDefinition,
9
+ type RouteDefinition,
10
+ type WorkspaceDefinition,
11
+ } from '@openmrs/esm-globals';
12
+ import { getFeatureFlag } from '@openmrs/esm-feature-flags';
13
+ import { routeRegex } from './helpers';
14
+ import { getLoader } from './app';
15
+ import { tryRegisterExtension, tryRegisterFeatureFlag, tryRegisterModal, tryRegisterWorkspace } from './components';
16
+
17
+ // this is the global holder of all pages registered in the app
18
+ const pages: Array<RegisteredPageDefinition> = [];
19
+
20
+ /**
21
+ * This takes a page's route definitions and returns a single-spa
22
+ * activityFn which returns true when the page matches the current
23
+ * route and false if it does not.
24
+ *
25
+ * @param route A string or regexp that matches the location when the
26
+ * page should be displayed, a boolean constant, or an array of such
27
+ * strings, regexps, and booleans
28
+ * @returns An activityFn suitable to use for a single-spa application
29
+ */
30
+ function getActivityFn(route: RouteDefinition | Array<RouteDefinition>): ActivityFn {
31
+ if (Array.isArray(route)) {
32
+ const activators = route.map(getActivityFn);
33
+ return (location) => activators.some((activator) => activator(location));
34
+ } else if (typeof route === 'string') {
35
+ return pathToActiveWhen(window.getOpenmrsSpaBase() + route);
36
+ } else if (route instanceof RegExp) {
37
+ return (location) => routeRegex(route, location);
38
+ } else {
39
+ return () => route;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * For pages, we also add support for rendered them based on online and offline mode as well as
45
+ * any feature flags.
46
+ *
47
+ * By default, we assume that all pages should be rendered when online, but only rendered
48
+ * offline if specifically configured to do so.
49
+ *
50
+ * @param activityFn A standard single-spa activityFn such as that returned by {@link getActivityFn()}
51
+ * @param pageDefinition The RegisteredPageDefinition object for this page
52
+ * @returns An activityFn suitable to use for a single-spa application
53
+ */
54
+ function wrapPageActivityFn(
55
+ activityFn: ActivityFn,
56
+ { online, offline, featureFlag }: RegisteredPageDefinition,
57
+ ): ActivityFn {
58
+ if (window.offlineEnabled) {
59
+ return (location) => {
60
+ // basically, if the page should only work online and we're offline or if the
61
+ // page should only work offline and we're online, defaulting to always rendering
62
+ // the page
63
+ if (!((navigator.onLine && (online ?? true)) || (!navigator.onLine && (offline ?? false)))) {
64
+ return false;
65
+ }
66
+
67
+ if (featureFlag) {
68
+ if (!getFeatureFlag(featureFlag)) {
69
+ return false;
70
+ }
71
+ }
72
+
73
+ return activityFn(location);
74
+ };
75
+ } else {
76
+ return activityFn;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * This is the main entry-point for registering an app with the app shell.
82
+ * Each app has a name and should have a `routes.json` file that defines it's
83
+ * associated routes.
84
+ *
85
+ * @param appName The name of the application, e.g. `@openmrs/esm-my-app`
86
+ * @param routes A Javascript object that corresponds to the app's routes.json`
87
+ * definition.
88
+ */
89
+ export function registerApp(appName: string, routes: OpenmrsAppRoutes) {
90
+ if (appName && routes && typeof routes === 'object') {
91
+ registerModuleWithConfigSystem(appName);
92
+
93
+ const availableExtensions: Array<ExtensionDefinition> = routes.extensions ?? [];
94
+ const availableModals: Array<ModalDefinition> = routes.modals ?? [];
95
+ const availableWorkspaces: Array<WorkspaceDefinition> = routes.workspaces ?? [];
96
+ const availableFeatureFlags: Array<FeatureFlagDefinition> = routes.featureFlags ?? [];
97
+
98
+ routes.pages?.forEach((p) => {
99
+ if (
100
+ p &&
101
+ typeof p === 'object' &&
102
+ Object.hasOwn(p, 'component') &&
103
+ (Object.hasOwn(p, 'route') || Object.hasOwn(p, 'routeRegex') || Object.hasOwn(p, 'routes'))
104
+ ) {
105
+ pages.push({
106
+ ...p,
107
+ order: p.order ?? Number.MAX_SAFE_INTEGER,
108
+ appName,
109
+ });
110
+ } else {
111
+ console.warn(
112
+ `A page for ${appName} could not be registered as it does not appear to have the required properties`,
113
+ p,
114
+ );
115
+ }
116
+ });
117
+
118
+ availableExtensions.forEach((ext) => {
119
+ if (ext && typeof ext === 'object' && Object.hasOwn(ext, 'name') && Object.hasOwn(ext, 'component')) {
120
+ tryRegisterExtension(appName, ext);
121
+ } else {
122
+ console.warn(
123
+ `An extension for ${appName} could not be registered as it does not appear to have the required properties`,
124
+ ext,
125
+ );
126
+ }
127
+ });
128
+
129
+ availableModals.forEach((modal) => {
130
+ if (modal && typeof modal === 'object' && Object.hasOwn(modal, 'name') && Object.hasOwn(modal, 'component')) {
131
+ tryRegisterModal(appName, modal);
132
+ } else {
133
+ console.warn(
134
+ `A modal for ${appName} could not be registered as it does not appear to have the required properties`,
135
+ modal,
136
+ );
137
+ }
138
+ });
139
+
140
+ availableWorkspaces.forEach((workspace) => {
141
+ if (
142
+ workspace &&
143
+ typeof workspace === 'object' &&
144
+ Object.hasOwn(workspace, 'name') &&
145
+ Object.hasOwn(workspace, 'component')
146
+ ) {
147
+ tryRegisterWorkspace(appName, workspace);
148
+ } else {
149
+ console.warn(
150
+ `A workspace for ${appName} could not be registered as it does not appear to have the required properties`,
151
+ workspace,
152
+ );
153
+ }
154
+ });
155
+
156
+ availableFeatureFlags.forEach((featureFlag) => {
157
+ if (featureFlag && typeof featureFlag === 'object' && Object.hasOwn(featureFlag, 'featureFlag')) {
158
+ tryRegisterFeatureFlag(appName, featureFlag);
159
+ } else {
160
+ console.warn(
161
+ `A feature flag for ${appName} could not be registered as it does not appear to have the required properties`,
162
+ featureFlag,
163
+ );
164
+ }
165
+ });
166
+ }
167
+ }
168
+
169
+ /**
170
+ * This is called by the app shell once all route entries have been processed.
171
+ * This actually registers the pages with the application. This function is
172
+ * necessary to ensure that pages are rendered in the DOM according to their
173
+ * order definition, especially because certain pages _must_ be first in the DOM.
174
+ *
175
+ * Each page is rendered into a div with an appropriate name.
176
+ */
177
+ export function finishRegisteringAllApps() {
178
+ pages.sort((a, b) => {
179
+ let sort = a.order - b.order;
180
+ if (sort != 0) {
181
+ return sort;
182
+ }
183
+ return a.appName.localeCompare(b.appName, 'en');
184
+ });
185
+
186
+ // Create a div for each page. This ensures their DOM order.
187
+ // If we don't do this, Single-SPA 5 will create the DOM element only once
188
+ // the page becomes active, which makes it impossible to guarantee order.
189
+ let appIndices = new Map();
190
+ for (let page of pages) {
191
+ if (!appIndices.has(page.appName)) {
192
+ appIndices.set(page.appName, 0);
193
+ } else {
194
+ appIndices.set(page.appName, appIndices.get(page.appName) + 1);
195
+ }
196
+ const index = appIndices.get(page.appName);
197
+
198
+ const name = `${page.appName}-page-${index}`;
199
+ const div = document.createElement('div');
200
+ div.id = `single-spa-application:${name}`;
201
+ document.body.appendChild(div);
202
+ tryRegisterPage(name, page);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * This function converts each page definition into a single-spa application
208
+ * if that's possible. After this point, pages are rendered using single-spa's
209
+ * routing logic.
210
+ *
211
+ * @param appName The name of the app containing this page
212
+ * @param page An object that describes the page, derived from `routes.json`
213
+ */
214
+ function tryRegisterPage(appName: string, page: RegisteredPageDefinition) {
215
+ const route =
216
+ typeof page.route !== 'undefined'
217
+ ? page.route
218
+ : typeof page.routeRegex !== 'undefined'
219
+ ? new RegExp(page.routeRegex)
220
+ : false;
221
+
222
+ if (route === false) {
223
+ console.warn(
224
+ `A registered page definition is missing a route and thus cannot be registered.
225
+ To fix this, ensure that you define the "route" (or alternatively the "routeRegex") field inside the extension definition.`,
226
+ appName,
227
+ );
228
+ return;
229
+ }
230
+
231
+ if (!page.component) {
232
+ console.warn(
233
+ `A registered page definition is missing a component and thus cannot be registered.
234
+ To fix this, ensure that you define the "component" field inside the page definition.`,
235
+ appName,
236
+ );
237
+ return;
238
+ }
239
+
240
+ const activityFn = wrapPageActivityFn(getActivityFn(route), page);
241
+ const loader = getLoader(page.appName, page.component);
242
+ registerApplication(appName, loader, activityFn);
243
+ }
package/src/public.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './constants';
2
+ export * from './routes';
3
+ export { initializeApp } from './loaders';