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 () {
|
|
|
|
|
|
2021-12-29 16:31:17 -05:00
|
|
|
/** 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 = [];
|
|
|
|
|
|
2022-02-20 12:56:43 -05:00
|
|
|
gapp.overlay = Object.assign;
|
|
|
|
|
|
2024-09-14 16:59:24 -04:00
|
|
|
// extract function arguments grouped by type
|
2022-02-24 14:05:25 -05:00
|
|
|
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
|
2024-06-27 21:50:54 -04:00
|
|
|
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-06-27 21:50:54 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
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
|
2022-02-24 14:05:25 -05:00
|
|
|
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];
|
2022-02-22 00:05:29 -05:00
|
|
|
const root = self;
|
|
|
|
|
// optional fn to run before loading
|
2022-02-24 14:05:25 -05:00
|
|
|
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) {
|
2022-02-24 14:05:25 -05:00
|
|
|
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}`);
|
|
|
|
|
}
|
2022-02-24 14:05:25 -05:00
|
|
|
// 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];
|
2022-02-22 00:05:29 -05:00
|
|
|
}
|
2021-12-29 08:47:57 -05:00
|
|
|
}
|
2022-02-24 14:05:25 -05:00
|
|
|
let tmp = path[map] || {};
|
2024-06-27 21:50:54 -04:00
|
|
|
safeFN(fn, name)(root, exports => {
|
2024-09-14 16:59:24 -04:00
|
|
|
// map exports into module namespace when called
|
2022-02-24 14:05:25 -05:00
|
|
|
if (exports) {
|
|
|
|
|
return path[map] = Object.assign(tmp, exports);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-12-29 08:47:57 -05:00
|
|
|
}
|
2022-02-20 12:56:43 -05:00
|
|
|
// force runtime error if gapp.load() called gapp.main()
|
2021-12-29 08:47:57 -05:00
|
|
|
mods = null;
|
2022-02-20 12:56:43 -05:00
|
|
|
// optional if not called inline with startup
|
2022-02-24 14:05:25 -05:00
|
|
|
if (post) {
|
|
|
|
|
post(root);
|
|
|
|
|
}
|
2021-12-29 08:47:57 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
})();
|