fix(commands) implement commands execution and improve error messaging

This commit is contained in:
Benjamin Wegener
2024-01-14 15:19:42 +00:00
parent 29bf68a047
commit bea825b809

View File

@@ -5,6 +5,17 @@ import CetraPlugin from '../plugins/CetraPlugin';
import BaseComponent from './BaseComponent';
class Cetra extends Emitter {
static #ERRORS = {
INVALID_IDENTIFIER: 'INVALID_IDENTIFIER',
INVALID_ENTITY_TYPE: 'INVALID_ENTITY_TYPE',
INVALID_ENTITY: 'INVALID_ENTITY',
INVALID_ROOT: 'INVALID_ROOT',
INVALID_COMPONENT_TYPE: 'INVALID_COMPONENT_TYPE',
INVALID_PLUGIN_URL: 'INVALID_PLUGIN_URL',
INVALID_PLUGIN_TYPE: 'INVALID_PLUGIN_TYPE',
INVALID_COMMAND: 'INVALID_COMMAND',
COMMAND_NOT_FOUND: 'COMMAND_NOT_FOUND',
};
// class static globals
static #instances = new Map();
static #entityTypes = {
@@ -103,17 +114,9 @@ class Cetra extends Emitter {
}
if (typeof this[`add${entityType}s`] === 'undefined') {
this[`add${entityType}s`] = (entities) => {
if (!Array.isArray(entities)) {
if (typeof entities != 'string')
throw new TypeError(
`${entityType} is not of type array or string`
);
throw new TypeError(
`${entityType} is not of type array`
);
}
this[`add${entityType}s`] = function (entities) {
if (!Array.isArray(entities))
throw new TypeError(Cetra.#ERRORS.INVALID_ENTITY_TYPE);
entities.forEach(({ identifier, _obj }) => {
this[`register${entityType}`](identifier, _obj);
@@ -143,7 +146,11 @@ class Cetra extends Emitter {
*/
#addEntity(entityType, identifier, fn) {
if (typeof identifier != 'string') {
Logger.error(`invalid identifier for ${entityType} ${identifier}`);
Logger.error(
Cetra.#ERRORS.INVALID_IDENTIFIER,
entityType,
identifier
);
return false;
}
// get entityKey by its value
@@ -151,7 +158,7 @@ class Cetra extends Emitter {
return Cetra.#entityTypes[key] == entityType;
});
if (!entityKey) {
Logger.error(`invalid entity type ${entityType}`);
Logger.error(Cetra.#ERRORS.INVALID_ENTITY_TYPE, entityType);
return false;
}
@@ -163,16 +170,12 @@ class Cetra extends Emitter {
try {
if (typeof fn === 'undefined') {
Registry.unregister(uniqueId, this.#secretKey);
throw new TypeError(
`invalid entity constructor for ${entityType} ${identifier}`
);
throw new TypeError(Cetra.#ERRORS.INVALID_ENTITY);
}
if (!this.#isValidEntity(entityType, fn)) {
Registry.unregister(uniqueId, this.#secretKey);
throw new TypeError(
`invalid entity constructor for ${entityType} ${identifier}`
);
throw new TypeError(Cetra.#ERRORS.INVALID_ENTITY);
}
if (typeof fn == 'function') {
@@ -265,7 +268,7 @@ class Cetra extends Emitter {
this.#root = document.querySelector(this.#root);
if (!this.#root) {
Logger.error('No root found, defaulting to body');
Logger.error(Cetra.#ERRORS.INVALID_ROOT);
this.#root = document.body;
}
}
@@ -314,7 +317,7 @@ class Cetra extends Emitter {
try {
data = JSON.parse(val);
} catch (err) {
//Logger.error(err);
Logger.error(err);
return val;
}
@@ -339,7 +342,7 @@ class Cetra extends Emitter {
this.#internals.get('settings').get('observeOptions')
);
} catch (err) {
Logger.error('an error occured with the observer!', err);
Logger.error(err);
}
}
@@ -352,7 +355,7 @@ class Cetra extends Emitter {
*/
getPlugin(identifier) {
if (!(identifier instanceof String)) {
Logger.error('Plugin identifier is not a string');
Logger.error(Cetra.#ERRORS.INVALID_IDENTIFIER, identifier);
return undefined;
}
@@ -465,7 +468,8 @@ class Cetra extends Emitter {
if (typeof klass.register === 'function') {
return klass.register(uid);
}
return klass;
throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_TYPE);
}
if (typeof klass === 'function') {
@@ -478,20 +482,15 @@ class Cetra extends Emitter {
// what else could it be?
if (typeof klass !== 'object')
throw new TypeError(
'plugin is not of a valid plugin type (`CetraPlugin` or `object` or `function` or `url`)'
);
throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_TYPE);
if (
klass.url &&
(typeof klass.url !== 'string' || !this.#isUrl(klass.url))
)
throw new TypeError(
'plugin url is not of type string and/or no valid url'
);
throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_URL);
if (klass.plugin) {
Logger.info('registering plugin 5', klass);
return this.#initPlugin(klass.plugin);
}
@@ -542,10 +541,8 @@ class Cetra extends Emitter {
.get('settings')
.get('selector')}-id]`
)
) {
Logger.info('skipped element', comp);
)
continue;
}
this.#initComponent(comp);
}
@@ -647,7 +644,7 @@ class Cetra extends Emitter {
comp.getAttribute(this.#internals.get('settings').get('selector'));
if (typeof compType == 'undefined' || !compType) {
Logger.error(`no component type given`);
Logger.error(Cetra.#ERRORS.INVALID_COMPONENT_TYPE);
return null;
}
@@ -807,14 +804,15 @@ class Cetra extends Emitter {
obj: plugin,
parent: this.#identifier,
});
try {
if (!identifier) {
Logger.error('Plugin identifier is required');
Logger.error(Cetra.#ERRORS.INVALID_IDENTIFIER);
Registry.unregister(uniqueId, this.#secretKey);
return;
}
if (this.#internals.get('plugins').has(identifier)) {
Logger.log(`Overwrite plugin ${identifier}`);
Registry.unregister(uniqueId, this.#secretKey);
Registry.register({
key: this.#secretKey,
@@ -823,20 +821,12 @@ class Cetra extends Emitter {
});
}
if (!plugin) {
Logger.error(
`Plugin ${identifier} is not an url or a plugin instance or class`
);
Registry.unregister(uniqueId, this.#secretKey);
return;
}
if (!plugin) throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_TYPE);
if (typeof plugin === 'string') {
if (!this.#isUrl(plugin)) {
Logger.error(`Plugin ${identifier} has an invalid url: ${url}`);
Registry.unregister(uniqueId, this.#secretKey);
return;
}
if (!this.#isUrl(plugin))
throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_URL);
Logger.info(`Plugin ${identifier} is loaded from ${plugin}`);
this.#internals.get('plugins').set(identifier, {
plugin,
@@ -846,24 +836,26 @@ class Cetra extends Emitter {
return;
}
if (!['function', 'object'].includes(typeof plugin)) {
Logger.error('Plugin is not of type function or object');
Registry.unregister(uniqueId, this.#secretKey);
return null;
}
if (!['function', 'object'].includes(typeof plugin))
throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_TYPE);
const pluginInstance = this.#initPlugin(plugin);
Registry.unregister(uniqueId, this.#secretKey);
if (!pluginInstance)
throw new TypeError('plugin is not of a valid plugin type');
throw new TypeError(Cetra.#ERRORS.INVALID_PLUGIN_TYPE);
Registry.register({
key: this.#secretKey,
obj: pluginInstance,
key: this.#secretKey,
parent: this.#identifier,
});
this.#internals.get('plugins').set(identifier, pluginInstance);
this.emit('onAfterRegisterPlugin', pluginInstance);
} catch (err) {
Logger.error(err);
Registry.unregister(uniqueId, this.#secretKey);
}
}
/**
@@ -875,26 +867,35 @@ class Cetra extends Emitter {
* @param {any} e - The event object.
* @throws {Error} If the component with the given ID is not found.
*/
exec(action, varName, componentId, e) {
exec(componentId, update = { command, args, evt }) {
if (Array.isArray(update.args)) update.args = [];
const comp = this.#internals.get('compIndex').get(componentId);
if (!comp) {
throw new Error(`component ${componentId} not found`);
}
if (this.#internals.get('plugins').get('utils')[action]) {
const value = comp.getValue(varName);
comp.update([
{
old: value,
new: this.#internals
.get('plugins')
.get('utils')
[action](comp.getValue(varName)),
varName,
},
]);
if (!this.#internals.get('commands').has(update.command)) {
Logger.error(Cetra.#ERRORS.COMMAND_NOT_FOUND, update.command);
return;
}
this.#internals
.get('commands')
.get(update.command)
.forEach((command) => {
if (!command.exec) {
if (typeof command != 'function' || !command.name) {
Logger.error(
Cetra.#ERRORS.INVALID_COMMAND,
update.command
);
}
command(comp, update);
}
command.exec(comp, update);
});
}
}