grid-apps-cmms/src.old/main/gapp.js

151 lines
3.9 KiB
JavaScript
Raw Normal View History

2021-12-29 08:47:57 -05:00
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
2021-12-29 10:37:17 -05:00
/** node compatibility **/
if (typeof(self) === 'undefined') {
2022-01-07 18:38:14 -05:00
this.self = this;
2021-12-29 10:37:17 -05:00
}
2021-12-29 08:47:57 -05:00
(function () {
/** satisfy earcut, tween, etc **/
if (!self.module) self.module = { exports: {} };
2021-12-29 08:47:57 -05:00
/** debug and logging **/
let mark = Date.now();
let since = () => {
return ((Date.now() - mark) / 1000).toFixed(2).padStart(9,0);
};
let dbug = self.dbug = self.dbug || {
level: 1, // 0=debug, 1=normal, 2=warn, 3=error
set: (level) => {
if (level >= 0) dbug.level = Math.min(level, 3);
},
debug: function() {
if (dbug.level <= 0) return console.log(since(),'[DBG]', ...arguments);
},
log: function() {
if (dbug.level <= 1) return console.log(since(),'|',...arguments);
},
warn: function() {
if (dbug.level <= 2) return console.log(since(),'[WRN]', ...arguments);
},
error: function() {
if (dbug.level <= 3) return console.trace(since(),'[ERR]', ...arguments);
2022-01-07 14:39:32 -05:00
},
since
2021-12-29 08:47:57 -05:00
};
/** empty function. countless possible uses **/
self.noop = () => {};
/** grid app container **/
let gapp = self.gapp = self.gapp || {};
// modules to load
let mods = [];
gapp.overlay = Object.assign;
2024-09-14 16:59:24 -04:00
// extract function arguments grouped by type
function exargs(args) {
return {
funcs: args.filter(a => typeof a === 'function'),
arrays: args.filter(a => Array.isArray(a)),
strings: args.filter(a => typeof a === 'string'),
objects: args.filter(a => typeof a === 'object' && !Array.isArray(a))
};
}
2021-12-29 08:47:57 -05:00
2024-09-14 16:59:24 -04:00
// prevent module load from terminating main/init chain
function safeFN(fn, name) {
return function() {
try {
return fn(...arguments);
} catch (error) {
2024-09-14 22:35:29 -04:00
if (error.stack) {
console.log(`[${name}]`, error.stack);
} else {
console.log({ register_fail: name, error });
}
}
};
}
2024-09-14 16:59:24 -04:00
// register module without a load function
gapp.register = function() {
const args = exargs([...arguments]);
const objs = args.objects || {};
const name = objs.name || objs.module || args.strings[0];
const fn = objs.exec || args.funcs[0];
const mod = { fn, name };
mods.push(mod);
};
2021-12-29 08:47:57 -05:00
// perform dependency checks and run module load functions
gapp.main = function() {
const args = exargs([...arguments]);
2024-09-14 16:59:24 -04:00
const objs = args.objects[0] || {};
const app = objs.app || args.strings[0];
const post = objs.post || args.funcs[0];
const pre = objs.pre || args.funcs[1];
const root = self;
// optional fn to run before loading
if (pre) {
pre(root);
}
2021-12-29 08:47:57 -05:00
// load mods after checking if dependency is present
for (let mod of mods) {
let { fn, name } = mod;
2021-12-29 08:47:57 -05:00
// mods with no name can't be depended on, but are allowed
if (name) {
dbug.debug(`${app} | load | ${name}`);
}
// modules without functions allowed so they can be depended on
if (!fn) {
dbug.debug(`${app} | ${mod.name} | missing fn()`);
continue;
}
// create namespace path in root and execute module load function
let toks = name.split('.');
let map = toks.pop();
let path = root;
for (let tok of toks) {
if (!path[tok]) {
dbug.debug({creating_root: tok, for: name});
path = path[tok] = {};
} else {
path = path[tok];
}
2021-12-29 08:47:57 -05:00
}
let tmp = path[map] || {};
safeFN(fn, name)(root, exports => {
2024-09-14 16:59:24 -04:00
// map exports into module namespace when called
if (exports) {
return path[map] = Object.assign(tmp, exports);
}
});
2021-12-29 08:47:57 -05:00
}
// force runtime error if gapp.load() called gapp.main()
2021-12-29 08:47:57 -05:00
mods = null;
// optional if not called inline with startup
if (post) {
post(root);
}
2021-12-29 08:47:57 -05:00
};
})();