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