/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
(function () {
const root = this;
if (!root.Espo) {
root.Espo = {};
}
if (root.Espo.loader) {
throw new Error("Loader was already loaded.");
}
/**
* A callback with resolved dependencies passed as parameters.
* Should return a value to define a module.
*
* @callback Loader~requireCallback
* @param {...any} arguments Resolved dependencies.
* @returns {*}
*/
/**
* @typedef {Object} Loader~libData
* @property {string} [exportsTo] Exports to.
* @property {string} [exportsAs] Exports as.
* @property {boolean} [sourceMap] Has a source map.
* @property {string} [exposeAs] To expose to global as.
* @property {string} [path] A path.
* @property {string} [devPath] A path in developer mode.
*/
/**
* @typedef {Object} Loader~dto
* @property {string} path
* @property {function(value): void} callback
* @property {function|null} [errorCallback]
* @property {'script'|'text'} dataType
* @property {string} id
* @property {'amd'|'lib'|'res'} type
* @property {string|null} exportsTo
* @property {string|null} exportsAs
* @property {string} [url]
* @property {boolean} [useCache]
*/
/**
* A loader. Used for loading and defining AMD modules, resource loading.
* Handles caching.
*/
class Loader {
/**
* @param {int|null} [_cacheTimestamp=null]
*/
constructor(_cacheTimestamp) {
this._cacheTimestamp = _cacheTimestamp || null;
/** @type {Object.} */
this._libsConfig = {};
this._loadCallbacks = {};
this._pathsBeingLoaded = {};
this._dataLoaded = {};
this._definedMap = {};
this._aliasMap = {};
this._contextId = null;
this._responseCache = null;
this._basePath = '';
this._internalModuleList = [];
this._transpiledModuleList = [];
this._internalModuleMap = {};
this._isDeveloperMode = false;
let baseUrl = window.location.origin + window.location.pathname;
if (baseUrl.slice(-1) !== '/') {
baseUrl = window.location.pathname.includes('.') ?
baseUrl.slice(0, baseUrl.lastIndexOf('/')) + '/' :
baseUrl + '/';
}
this._baseUrl = baseUrl;
this._isDeveloperModeIsSet = false;
this._basePathIsSet = false;
this._responseCacheIsSet = false;
this._internalModuleListIsSet = false;
this._bundleFileMap = {};
this._bundleMapping = {};
/** @type {Object.} */
this._bundleDependenciesMap = {};
/** @type {Object.} */
this._bundlePromiseMap = {};
this._addLibsConfigCallCount = 0;
this._addLibsConfigCallMaxCount = 2;
/** @type {Object.} */
this._urlIdMap = {};
}
/**
* @param {boolean} isDeveloperMode
*/
setIsDeveloperMode(isDeveloperMode) {
if (this._isDeveloperModeIsSet) {
throw new Error('Is-Developer-Mode is already set.');
}
this._isDeveloperMode = isDeveloperMode;
this._isDeveloperModeIsSet = true;
}
/**
* @param {string} basePath
*/
setBasePath(basePath) {
if (this._basePathIsSet) {
throw new Error('Base path is already set.');
}
this._basePath = basePath;
this._basePathIsSet = true;
}
/**
* @returns {Number}
*/
getCacheTimestamp() {
return this._cacheTimestamp;
}
/**
* @param {Number} cacheTimestamp
*/
setCacheTimestamp(cacheTimestamp) {
this._cacheTimestamp = cacheTimestamp;
}
/**
* @param {Cache} responseCache
*/
setResponseCache(responseCache) {
if (this._responseCacheIsSet) {
throw new Error('Response-Cache is already set');
}
this._responseCache = responseCache;
this._responseCacheIsSet = true;
}
/**
* @param {string[]} internalModuleList
*/
setInternalModuleList(internalModuleList) {
if (this._internalModuleListIsSet) {
throw new Error('Internal-module-list is already set');
}
this._internalModuleList = internalModuleList;
this._internalModuleMap = {};
this._internalModuleListIsSet = true;
}
/**
* @param {string[]} transpiledModuleList
*/
setTranspiledModuleList(transpiledModuleList) {
this._transpiledModuleList = transpiledModuleList;
}
/**
* @private
* @param {string} id
*/
_get(id) {
if (id in this._definedMap) {
return this._definedMap[id];
}
return void 0;
}
/**
* @private
* @param {string} id
* @param {*} value
*/
_set(id, value) {
this._definedMap[id] = value;
if (id.slice(0, 4) === 'lib!') {
const libName = id.slice(4);
const libsData = this._libsConfig[libName];
if (libsData && libsData.exposeAs) {
const key = libsData.exposeAs;
window[key] = value;
}
}
}
/**
* @private
* @param {string} id
* @return {string}
*/
_idToPath(id) {
if (id.indexOf(':') === -1) {
return 'client/lib/transpiled/src/' + id + '.js';
}
const [mod, namePart] = id.split(':');
if (mod === 'custom') {
return 'client/custom/src/' + namePart + '.js';
}
const transpiled = this._transpiledModuleList.includes(mod);
const internal = this._isModuleInternal(mod);
if (transpiled) {
if (internal) {
return `client/lib/transpiled/modules/${mod}/src/${namePart}.js`;
}
return `client/custom/modules/${mod}/lib/transpiled/src/${namePart}.js`;
}
if (internal) {
return 'client/modules/' + mod + '/src/' + namePart + '.js';
}
return 'client/custom/modules/' + mod + '/src/' + namePart + '.js';
}
/**
* @private
* @param {string} id
* @param {*} value
*/
_executeLoadCallback(id, value) {
if (!(id in this._loadCallbacks)) {
return;
}
this._loadCallbacks[id].forEach(callback => callback(value));
delete this._loadCallbacks[id];
}
/**
* Define a module.
*
* @param {string|null} id A module name to be defined.
* @param {string[]} dependencyIds A dependency list.
* @param {Loader~requireCallback} callback A callback with resolved dependencies
* passed as parameters. Should return a value to define the module.
*/
define(id, dependencyIds, callback) {
if (id) {
id = this._normalizeId(id);
}
if (!id && document.currentScript) {
const src = document.currentScript.src;
id = this._urlIdMap[src];
delete this._urlIdMap[src];
}
if (!id && this._contextId) {
id = this._contextId;
}
this._contextId = null;
const existing = this._get(id);
if (typeof existing !== 'undefined') {
return;
}
if (!dependencyIds) {
this._defineProceed(callback, id, [], -1);
return;
}
const indexOfExports = dependencyIds.indexOf('exports');
if (Array.isArray(dependencyIds)) {
dependencyIds = dependencyIds.map(depId => this._normalizeIdPath(depId, id));
}
this.require(dependencyIds, (...args) => {
this._defineProceed(callback, id, args, indexOfExports);
});
}
/**
* @private
* @param {function} callback
* @param {string} id
* @param {Array} args
* @param {number} indexOfExports
*/
_defineProceed(callback, id, args, indexOfExports) {
let value = callback.apply(root, args);
if (typeof value === 'undefined' && indexOfExports === -1 && id) {
throw new Error(`Could not load '${id}'.`);
}
if (indexOfExports !== -1) {
const exports = args[indexOfExports];
// noinspection JSUnresolvedReference
value = ('default' in exports) ? exports.default : exports;
}
if (!id) {
console.warn(`Lib without id.`);
// Libs can define w/o id and set to the root.
// Not supposed to happen as should be suppressed by define.amd = false;
return;
}
this._set(id, value);
this._executeLoadCallback(id, value);
}
/**
* Require a module or multiple modules.
*
* @param {string|string[]} id A module or modules to require.
* @param {Loader~requireCallback} callback A callback with resolved dependencies.
* @param {Function|null} [errorCallback] An error callback.
*/
require(id, callback, errorCallback) {
let list;
if (Object.prototype.toString.call(id) === '[object Array]') {
list = id;
list.forEach((item, i) => {
list[i] = this._normalizeId(item);
});
}
else if (id) {
id = this._normalizeId(id);
list = [id];
}
else {
list = [];
}
const totalCount = list.length;
if (totalCount === 1) {
this._load(list[0], callback, errorCallback);
return;
}
if (totalCount) {
let readyCount = 0;
const loaded = {};
list.forEach(depId => {
this._load(depId, c => {
loaded[depId] = c;
readyCount++;
if (readyCount === totalCount) {
const args = [];
for (const i in list) {
args.push(loaded[list[i]]);
}
callback.apply(root, args);
}
});
});
return;
}
callback.apply(root);
}
/**
* @private
*/
_convertCamelCaseToHyphen(string) {
if (string === null) {
return string;
}
return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
/**
* @param {string} id
* @param {string} subjectId
* @private
*/
_normalizeIdPath(id, subjectId) {
if (id.charAt(0) !== '.') {
return id;
}
if (id.slice(0, 2) !== './' && id.slice(0, 3) !== '../') {
return id;
}
let outputPath = id;
const dirParts = subjectId.split('/').slice(0, -1);
if (id.slice(0, 2) === './') {
outputPath = dirParts.join('/') + '/' + id.slice(2);
}
const parts = outputPath.split('/');
let up = 0;
for (const part of parts) {
if (part === '..') {
up++;
continue;
}
break;
}
if (!up) {
return outputPath;
}
if (up) {
outputPath = dirParts.slice(0, -up).join('/') + '/' + outputPath.slice(3 * up);
}
return outputPath;
}
/**
* @private
* @param {string} id
* @return {string}
*/
_restoreId(id) {
if (!id.includes(':')) {
return id;
}
const [mod, part] = id.split(':');
return `modules/${mod}/${part}`;
}
/**
* @private
* @param {string} id
* @return {string}
*/
_normalizeId(id) {
if (id in this._aliasMap) {
id = this._aliasMap[id];
}
if (~id.indexOf('.') && !~id.indexOf('!') && id.slice(-3) !== '.js') {
console.warn(`${id}: module ID should use slashes instead of dots and hyphen instead of CamelCase.`);
}
if (!!/[A-Z]/.exec(id[0])) {
if (id.indexOf(':') !== -1) {
const arr = id.split(':');
const modulePart = arr[0];
const namePart = arr[1];
return this._convertCamelCaseToHyphen(modulePart) + ':' +
this._convertCamelCaseToHyphen(namePart)
.split('.')
.join('/');
}
return this._convertCamelCaseToHyphen(id).split('.').join('/');
}
if (id.startsWith('modules/')) {
id = id.slice(8);
const index = id.indexOf('/');
if (index > 0) {
const mod = id.slice(0, index);
id = id.slice(index + 1);
return mod + ':' + id;
}
}
return id;
}
/**
* @private
* @param {string} id
* @param {function(*)} callback
*/
_addLoadCallback(id, callback) {
if (!(id in this._loadCallbacks)) {
this._loadCallbacks[id] = [];
}
this._loadCallbacks[id].push(callback);
}
/**
* @private
* @param {string} id
* @param {function(*)} callback
* @param {function()} [errorCallback]
*/
_load(id, callback, errorCallback) {
if (id === 'exports') {
callback({});
return;
}
let dataType, type, path, exportsTo, exportsAs;
let realName = id;
if (id.indexOf('lib!') === 0) {
dataType = 'script';
type = 'lib';
realName = id.slice(4);
path = realName;
exportsTo = 'window';
exportsAs = null;
const isDefinedLib = realName in this._libsConfig;
if (isDefinedLib) {
const libData = this._libsConfig[realName] || {};
path = libData.path || path;
if (this._isDeveloperMode && libData.devPath) {
path = libData.devPath;
}
exportsTo = libData.exportsTo || null;
exportsAs = libData.exportsAs || null;
}
if (isDefinedLib && !exportsTo) {
type = 'amd';
}
if (path.indexOf(':') !== -1) {
console.error(`Not allowed path '${path}'.`);
throw new Error();
}
let obj = void 0;
if (exportsTo && exportsAs) {
obj = this._fetchObject(exportsTo, exportsAs);
}
if (typeof obj === 'undefined' && id in this._definedMap) {
obj = this._definedMap[id];
}
if (typeof obj !== 'undefined') {
callback(obj);
return;
}
} else if (id.indexOf('res!') === 0) {
dataType = 'text';
type = 'res';
realName = id.slice(4);
path = realName;
if (path.indexOf(':') !== -1) {
console.error(`Not allowed path '${path}'.`);
throw new Error();
}
} else {
dataType = 'script';
type = 'amd';
if (!id || id === '') {
throw new Error("Can't load with empty module ID.");
}
const value = this._get(id);
if (typeof value !== 'undefined') {
callback(value);
return;
}
const restoredId = this._restoreId(id);
if (restoredId in this._bundleMapping) {
const bundleName = this._bundleMapping[restoredId];
this._requireBundle(bundleName).then(() => {
const value = this._get(id);
if (typeof value === 'undefined') {
const msg = `Could not obtain module '${restoredId}' from bundle '${bundleName}'.`;
console.error(msg);
throw new Error(msg);
}
callback(value);
});
return;
}
path = this._idToPath(id);
}
if (id in this._dataLoaded) {
callback(this._dataLoaded[id]);
return;
}
/** @type {Loader~dto} */
const dto = {
id: id,
type: type,
dataType: dataType,
path: path,
callback: callback,
errorCallback: errorCallback,
exportsAs: exportsAs,
exportsTo: exportsTo,
};
if (path in this._pathsBeingLoaded) {
this._addLoadCallback(id, callback);
return;
}
this._pathsBeingLoaded[path] = true;
let useCache = false;
if (this._cacheTimestamp) {
useCache = true;
const sep = (path.indexOf('?') > -1) ? '&' : '?';
path += sep + 'r=' + this._cacheTimestamp;
}
const url = this._basePath + path;
dto.path = path;
dto.url = url;
dto.useCache = useCache;
if (dto.dataType === 'script') {
this._addLoadCallback(id, callback);
const urlObj = new URL(this._baseUrl + url);
if (!useCache) {
urlObj.searchParams.append('_', Date.now().toString())
}
const fullUrl = urlObj.toString();
if (type === 'amd') {
this._urlIdMap[fullUrl] = id;
}
this._addScript(fullUrl, () => {
let value;
if (type === 'amd') {
value = this._get(id);
if (typeof value !== 'undefined') {
this._executeLoadCallback(id, value);
return;
}
// Supposed to be handled by the added callback.
return;
}
if (exportsTo && exportsAs) {
value = this._fetchObject(exportsTo, exportsAs);
this._dataLoaded[id] = value;
this._executeLoadCallback(id, value);
return;
}
if (type === 'lib') {
this._dataLoaded[id] = undefined;
this._executeLoadCallback(id, undefined);
return;
}
console.warn(`Could not obtain ${id}.`);
}, errorCallback);
return;
}
if (!this._responseCache) {
this._processRequest(dto);
return;
}
this._responseCache
.match(new Request(url))
.then(response => {
if (!response) {
this._processRequest(dto);
return;
}
response.text()
.then(text => this._handleResponseText(dto, text));
});
}
/**
* @private
* @param {string} url
* @param {function} callback
* @param {function|null} [errorCallback]
* @return {Promise}
*/
_addScript(url, callback, errorCallback = null) {
const script = document.createElement('script');
script.src = url;
script.async = true;
script.addEventListener('error', e => {
console.error(`Could not load script '${url}'.`, e);
if (errorCallback) {
errorCallback();
}
});
document.head.appendChild(script);
script.addEventListener('load', () => callback());
}
/**
* @private
* @param {string} name
* @return {Promise}
*/
_requireBundle(name) {
if (this._bundlePromiseMap[name]) {
return this._bundlePromiseMap[name];
}
const dependencies = this._bundleDependenciesMap[name] || [];
if (!dependencies.length) {
this._bundlePromiseMap[name] = this._addBundle(name);
return this._bundlePromiseMap[name];
}
this._bundlePromiseMap[name] = new Promise(resolve => {
const list = dependencies.map(item => {
if (item.indexOf('bundle!') === 0) {
return this._requireBundle(item.substring(7));
}
return Espo.loader.requirePromise(item);
});
Promise.all(list)
.then(() => this._addBundle(name))
.then(() => resolve());
});
return this._bundlePromiseMap[name];
}
/**
* @private
* @param {string} name
* @return {Promise}
*/
_addBundle(name) {
let src = this._bundleFileMap[name];
if (!src) {
throw new Error(`Unknown bundle '${name}'.`);
}
if (this._cacheTimestamp) {
const sep = (src.indexOf('?') > -1) ? '&' : '?';
src += sep + 'r=' + this._cacheTimestamp;
}
src = this._basePath + src;
const script = document.createElement('script');
script.src = src;
script.async = true;
script.addEventListener('error', event => {
console.error(`Could not load bundle '${name}'.`, event);
});
return new Promise(resolve => {
document.head.appendChild(script);
script.addEventListener('load', () => resolve());
});
}
/**
* @private
* @return {*}
*/
_fetchObject(exportsTo, exportsAs) {
let from = root;
if (exportsTo === 'window') {
from = root;
}
else {
for (const item of exportsTo.split('.')) {
from = from[item];
if (typeof from === 'undefined') {
return void 0;
}
}
}
if (exportsAs in from) {
return from[exportsAs];
}
return void 0;
}
/**
* @private
* @param {Loader~dto} dto
*/
_processRequest(dto) {
const url = dto.url;
const errorCallback = dto.errorCallback;
const path = dto.path;
const useCache = dto.useCache;
const urlObj = new URL(this._baseUrl + url);
if (!useCache) {
urlObj.searchParams.append('_', Date.now().toString())
}
fetch(urlObj)
.then(response => {
if (!response.ok) {
if (typeof errorCallback === 'function') {
errorCallback();
return;
}
throw new Error(`Could not fetch asset '${path}'.`);
}
response.text().then(text => {
if (this._responseCache) {
this._responseCache.put(url, new Response(text));
}
this._handleResponseText(dto, text);
});
})
.catch(() => {
if (typeof errorCallback === 'function') {
errorCallback();
return;
}
throw new Error(`Could not fetch asset '${path}'.`);
});
}
/**
* @private
* @param {Loader~dto} dto
* @param {string} text
*/
_handleResponseText(dto, text) {
const id = dto.id;
const callback = dto.callback;
this._addLoadCallback(id, callback);
this._dataLoaded[id] = text;
this._executeLoadCallback(id, text);
}
/**
* @param {Object.} data
* @internal
*/
addLibsConfig(data) {
if (this._addLibsConfigCallCount === this._addLibsConfigCallMaxCount) {
throw new Error("Not allowed to call addLibsConfig.");
}
this._addLibsConfigCallCount++;
this._libsConfig = {...this._libsConfig, ...data};
}
/**
* @param {Object.} map
*/
setAliasMap(map) {
this._aliasMap = map;
}
/**
* @private
*/
_isModuleInternal(moduleName) {
if (!(moduleName in this._internalModuleMap)) {
this._internalModuleMap[moduleName] = this._internalModuleList.indexOf(moduleName) !== -1;
}
return this._internalModuleMap[moduleName];
}
/**
* @param {string} name A bundle name.
* @param {string} file A bundle file.
* @internal
*/
mapBundleFile(name, file) {
this._bundleFileMap[name] = file;
}
/**
* @param {string} name A bundle name.
* @param {string[]} list Dependencies.
* @internal
*/
mapBundleDependencies(name, list) {
this._bundleDependenciesMap[name] = list;
}
/**
* @param {Object.} mapping
* @internal
*/
addBundleMapping(mapping) {
Object.assign(this._bundleMapping, mapping);
}
/**
* @param {string} id
* @internal
*/
setContextId(id) {
this._contextId = id;
}
/**
* Require a module.
*
* @param {string} id A module to require.
* @returns {Promise<*>}
*/
requirePromise(id) {
return new Promise((resolve, reject) => {
this.require(
id,
arg => resolve(arg),
() => reject()
);
});
}
}
const loader = new Loader();
// noinspection JSUnusedGlobalSymbols
Espo.loader = {
/**
* @param {boolean} isDeveloperMode
* @internal
*/
setIsDeveloperMode: function (isDeveloperMode) {
loader.setIsDeveloperMode(isDeveloperMode);
},
/**
* @param {string} basePath
* @internal
*/
setBasePath: function (basePath) {
loader.setBasePath(basePath);
},
/**
* @returns {Number}
*/
getCacheTimestamp: function () {
return loader.getCacheTimestamp();
},
/**
* @param {Number} cacheTimestamp
* @internal
*/
setCacheTimestamp: function (cacheTimestamp) {
loader.setCacheTimestamp(cacheTimestamp);
},
/**
* @param {Cache} responseCache
* @internal
*/
setResponseCache: function (responseCache) {
loader.setResponseCache(responseCache);
},
/**
* Define a module.
*
* @param {string} id A module name to be defined.
* @param {string[]} dependencyIds A dependency list.
* @param {Loader~requireCallback} callback A callback with resolved dependencies
* passed as parameters. Should return a value to define the module.
*/
define: function (id, dependencyIds, callback) {
loader.define(id, dependencyIds, callback);
},
/**
* Require a module or multiple modules.
*
* @param {string|string[]} id A module or modules to require.
* @param {Loader~requireCallback} callback A callback with resolved dependencies.
* @param {Function|null} [errorCallback] An error callback.
*/
require: function (id, callback, errorCallback) {
loader.require(id, callback, errorCallback);
},
/**
* Require a module or multiple modules.
*
* @param {string|string[]} id A module or modules to require.
* @returns {Promise}
*/
requirePromise: function (id) {
return loader.requirePromise(id);
},
/**
* @param {Object.} data
* @internal
*/
addLibsConfig: function (data) {
loader.addLibsConfig(data);
},
/**
* @param {string} name A bundle name.
* @param {string} file A bundle file.
* @internal
*/
mapBundleFile: function (name, file) {
loader.mapBundleFile(name, file);
},
/**
* @param {string} name A bundle name.
* @param {string[]} list Dependencies.
* @internal
*/
mapBundleDependencies: function (name, list) {
loader.mapBundleDependencies(name, list);
},
/**
* @param {Object.} mapping
* @internal
*/
addBundleMapping: function (mapping) {
loader.addBundleMapping(mapping);
},
/**
* @param {string} id
* @internal
*/
setContextId: function (id) {
loader.setContextId(id);
},
};
/**
* Require a module or multiple modules.
*
* @param {string|string[]} id A module or modules to require.
* @param {Loader~requireCallback} callback A callback with resolved dependencies.
* @param {Object} [context] A context.
* @param {Function|null} [errorCallback] An error callback.
*
* @deprecated Use `Espo.loader.require` instead.
*/
root.require = Espo.require = function (id, callback, context, errorCallback) {
if (context) {
callback = callback.bind(context);
}
loader.require(id, callback, errorCallback);
};
/**
* Define an [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) module.
*
* 3 signatures:
* 1. `(callback)` – Unnamed, no dependencies.
* 2. `(dependencyList, callback)` – Unnamed, with dependencies.
* 3. `(moduleName, dependencyList, callback)` – Named.
*
* @param {string|string[]|Loader~requireCallback} arg1 A module name to be defined,
* a dependency list or a callback.
* @param {string[]|Loader~requireCallback} [arg2] A dependency list or a callback with resolved
* dependencies.
* @param {Loader~requireCallback} [arg3] A callback with resolved dependencies.
*/
root.define = Espo.define = function (arg1, arg2, arg3) {
let id = null;
let depIds = null;
let callback;
if (typeof arg1 === 'function') {
callback = arg1;
} else if (typeof arg1 !== 'undefined' && typeof arg2 === 'function') {
if (Array.isArray(arg1)) {
depIds = arg1;
} else {
id = arg1;
depIds = [];
}
callback = arg2;
} else {
id = arg1;
depIds = arg2;
callback = arg3;
}
loader.define(id, depIds, callback);
};
root.define.amd = true;
(() => {
const loaderParamsTag = document.querySelector('script[data-name="loader-params"]');
if (!loaderParamsTag) {
return;
}
/**
* @type {{
* cacheTimestamp?: int,
* basePath?: string,
* internalModuleList?: [],
* transpiledModuleList?: [],
* libsConfig?: Object.,
* aliasMap?: Object.,
* }}
*/
const params = JSON.parse(loaderParamsTag.textContent);
loader.setCacheTimestamp(params.cacheTimestamp);
loader.setBasePath(params.basePath);
loader.setInternalModuleList(params.internalModuleList);
loader.setTranspiledModuleList(params.transpiledModuleList);
loader.addLibsConfig(params.libsConfig);
loader.setAliasMap(params.aliasMap);
})();
}).call(window);