atriusmaps-node-sdk
Version:
This project provides an API to Atrius Personal Wayfinder maps within a Node environment. See the README.md for more information
187 lines (154 loc) • 6.85 kB
JavaScript
;
var R = require('ramda');
var Zousan = require('zousan-plus');
var _package = require('../package.json.js');
var debugTools = require('./debugTools.js');
var env = require('./env.js');
var bustle = require('./extModules/bustle.js');
var log = require('./extModules/log.js');
var i18n = require('./utils/i18n.js');
function _interopNamespaceDefaultOnly (e) { return Object.freeze({ __proto__: null, default: e }); }
const isBrowser = typeof window !== 'undefined';
const TRACE = false;
async function setupPlugin(app, id, config) {
let name = id;
if (name.includes('/')) {
const split = name.split('/');
name = split[split.length - 1];
}
if (config.active !== undefined) {
if (config.active === false || (config.active === 'notLocalhost' && app.env.isLocalhost())) {
app.log.info(`Plugin ${id} explicitly deativated`);
return null;
}
}
return import(`../plugins/${id}/src/${name}.js`).then(pluginModule => {
app.log.info(`Creating plugin ${id}`);
return pluginModule.create(app, config);
});
}
// takes the `lang` query parameter and returns the most specific supported language
// Recognizes the following optional configuration parameters:
// supportedLanguages : array of supported language strings. i.e. [ "en", "en-US", "fr", "ja" ]
// defaultLanguage : if all fails, use this language. default = "en"
const getLang = config => {
const supportedLanguages = config.supportedLanguages || [
'ar',
'de',
'en',
'es',
'fr',
'hi',
'is',
'it',
'ja',
'ko',
'pl',
'pt',
'zh-Hans',
'zh-Hant',
'el-GR',
'th',
];
if (typeof window !== 'undefined') {
// if this is a browser...
const queryParms = new URLSearchParams(location.search);
// eslint-disable-next-line no-constant-condition
let lang = queryParms.get('lang') || (typeof navigator ? navigator.language : null);
while (lang)
if (lang && supportedLanguages.includes(lang)) return lang;
else lang = lang.substring(0, lang.lastIndexOf('-'));
}
return config.defaultLanguage || 'en';
};
async function loadConfig(name) {
return isBrowser ? import(`./configs/${name}.json`) : import(`./configs/${name}.json.js`); // bit of a hack - but supports all versions of node. See https://gitlab.com/locuslabspublic/node-sdk/-/merge_requests/1
}
async function extendConfig(config, extendsConfigs) {
let newConfig = {};
const extConfigFiles = await Promise.all(extendsConfigs.map(loadConfig));
for (const extendsConfigMod of extConfigFiles) {
let extendsConfig = extendsConfigMod.default;
extendsConfig = extendsConfig.extends ? await extendConfig(extendsConfig, extendsConfig.extends) : extendsConfig; // enable recursive extends
newConfig = R.mergeDeepRight(newConfig, extendsConfig); // default is JSON data in ES6 modules import
}
newConfig = R.mergeDeepRight(newConfig, config);
return newConfig;
}
// const isSimpleName = name => /^[-a-zA-Z0-9]+$/.test(name) // composed of only alphanumeric and dash
const createPostProcessor = name => config => import(`./configs/postproc-${name}.js`).then(pp => pp.process(config));
const handleConfigPostProcess = async config =>
config.configPostProc ? Zousan.series(config, ...config.configPostProc.map(createPostProcessor)) : config;
async function create(rawConfig) {
const appInstance = Object.create(null);
let config = rawConfig.extends ? await extendConfig(rawConfig, rawConfig.extends) : rawConfig;
// this handles error reporting, so we want it activated ASAP
if (config.plugins.monitoring)
await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefaultOnly(require('../_virtual/_empty_module_placeholder.js')); }).then(mon => mon.activate(config.plugins.monitoring));
config = await handleConfigPostProcess(config);
const lang = getLang(config);
const i18n$1 = await i18n.default(lang, { debug: config.debug });
appInstance.i18n = () => i18n$1;
appInstance.gt = () => i18n$1.t.bind(i18n$1); // get translation function - don't hold this, it is bound to current lang
appInstance.config = config;
appInstance.plugins = {};
const appLog = log.initLog('web-engine', {
enabled: !!config.debug,
isBrowser,
color: 'cyan',
logFilter: config.logFilter,
truncateObjects: !isBrowser,
trace: TRACE,
});
appInstance.log = appLog.sublog(config.name);
appInstance.bus = bustle.create({
showEvents: true,
reportAllErrors: true,
log: appLog,
});
appInstance.info = { wePkg: _package.default }; // web-engine package
if (typeof window !== 'undefined') {
// Prepare for non-browser environments
if (config.debug) {
appInstance.debug = R.map(fn => fn.bind(appInstance), debugTools);
debugTools.dndGo.call(appInstance); // setup DnD by default...
} else appInstance.debug = {}; // no tools unless in debug mode.. (good idea?)
window._app = appInstance;
if (window.document && window.document.title && config.setWindowTitle) document.title = config.name;
}
appInstance.env = env.buildEnv(appInstance);
if (config.theme) {
// the following is only needed when UI is active - which requires a theme
await Zousan.evaluate(
{ name: 'ThemeManagerModule', value: Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefaultOnly(require('../_virtual/_empty_module_placeholder.js')); }) },
{ name: 'HistoryManager', value: Promise.resolve().then(function () { return require('./historyManager.js'); }) },
{ name: 'LayerManager', value: Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespaceDefaultOnly(require('../_virtual/_empty_module_placeholder.js')); }) },
).then(async ({ LayerManager, HistoryManager, ThemeManagerModule }) => {
const ThemeManager = ThemeManagerModule.initThemeManager(appInstance);
appInstance.themePack = await ThemeManager.buildTheme(config.theme, config.defaultTheme);
LayerManager.initLayerManager(appInstance);
HistoryManager.initHistoryManager(appInstance);
appInstance.destroy = () => LayerManager.destroy(appInstance);
});
} else appInstance.destroy = () => {}; // noop
if (config.plugins) {
for (const id in config.plugins) {
try {
const pluginConfig = config.plugins[id];
if (appInstance.plugins[id]) {
throw Error(`Duplicate plugin name "${id}"`);
}
const plugin = await setupPlugin(appInstance, id, pluginConfig);
if (plugin) appInstance.plugins[id] = plugin;
} catch (e) {
appLog.error('Error instantiating plugin ' + id);
appLog.error(e);
}
}
for (const id in appInstance.plugins) {
appInstance.plugins[id].init();
}
}
return appInstance;
}
exports.create = create;