castelog
Version:
Programación JavaScript en castellano.
329 lines (324 loc) • 18.3 kB
JavaScript
Castelog.metodos.una_proxificacion = function(...args) {
return new Castelog.variables.Proxificacion(...args);
};
Castelog.metodos.un_resultado_de_proxificacion = function (...args) {
return new Castelog.variables.Resultado_de_proxificacion(...args);
};
Castelog.variables.Resultado_de_proxificacion = class {
static factoria(dato) {
return new this(dato);
}
constructor(resultado) {
this.resultado = resultado;
}
};
Castelog.variables.Proxificacion = class {
static get Resultado_de_proxificacion() {
return Castelog.variables.Resultado_de_proxificacion;
}
constructor(dato_original) {
let proxy = undefined, dato = dato_original;
if (typeof dato_original === "function") {
proxy = Castelog.variables.Proxificacion.obtener_proxy_de_funcion(dato);
} else if (typeof dato_original === "object") {
proxy = Castelog.variables.Proxificacion.obtener_proxy_de_objeto(dato);
} else {
throw new Error("Required parameter «dato_original» to be object or function in order to «Proxificacion.constructor»");
}
return proxy;
}
static comprobar_tipo_de_evento(evento, dato) {
if ((typeof evento !== "string") || (["get", "set", "call"].indexOf(evento) === -1)) {
throw new Error("Required parameter «evento» to be a string and a known event type in order to «Proxificacion.comprobar_tipo_de_evento»");
}
return true;
}
static comprobar_accion_o_dato_de_accion(accion, dato) {
if(typeof accion === "function") {
return true;
} else if((typeof accion === "object") && Array.isArray(accion) && (accion.length > 0)) {
return true;
}
throw new Error("Required parameter «accion» to be a function or an array of more than 0 items in order to «Proxificacion.comprobar_accion_o_dato_de_accion»");
}
static comprobar_accion(accion, dato) {
if (typeof accion !== "function") {
throw new Error("Required parameter «accion» to be a function in order to «Proxificacion.comprobar_accion»");
}
return true;
}
static comprobar_configuracion(configuracion, dato) {
if (typeof configuracion !== "object") {
throw new Error("Required parameter «configuracion» to be an object in order to «Proxificacion.comprobar_configuracion»");
}
return true;
}
static extender_con_proxy_api(dato) {
dato.$proxy_api = {
debug: false,
eventos: {
para: {
get: [],
set: [],
call: [],
}
},
seleccionar: function (tipo_de_evento, filtro) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
Castelog.variables.Proxificacion.comprobar_accion(filtro);
return dato.$proxy.eventos.para[tipo_de_evento].filter(filtro);
},
insertar: function (tipo_de_evento, accion, configuracion = {}) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
Castelog.variables.Proxificacion.comprobar_accion(accion);
Castelog.variables.Proxificacion.comprobar_configuracion(configuracion);
const datos_de_evento = [accion, configuracion];
dato.$proxy_api.eventos.para[tipo_de_evento].push(datos_de_evento);
return datos_de_evento;
},
eliminar: function (tipo_de_evento, accion) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
Castelog.variables.Proxificacion.comprobar_accion_o_dato_de_accion(accion);
const checker = (typeof accion === "function") ? evento => evento[0] === accion : evento => evento === accion;
const evento = dato.$proxy_api.eventos.para[tipo_de_evento].filter(checker);
if (typeof evento === "undefined") {
throw new Error(`Required parameter «accion» to be known as an event function by «${tipo_de_evento}» in order to «proxificacion.$proxy_api.eliminar»`)
}
return dato.$proxy_api.eventos.para[tipo_de_evento].splice(
0 + dato.$proxy_api.eventos.para[tipo_de_evento].indexOf(evento),
1
);
},
actualizar: function (tipo_de_evento, accion, nueva_accion, nueva_configuracion = {}) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
Castelog.variables.Proxificacion.comprobar_accion_o_dato_de_accion(accion);
Castelog.variables.Proxificacion.comprobar_accion(nueva_accion);
const checker = (typeof accion === "function") ? evento => evento[0] === accion : evento => evento === accion;
const evento = dato.$proxy_api.eventos.para[tipo_de_evento].filter(checker);
if (typeof evento === "undefined") {
throw new Error(`Required parameter «accion» to be known as an event function by «${tipo_de_evento}» in order to «proxificacion.$proxy_api.actualizar»`)
}
return dato.$proxy_api.eventos.para[tipo_de_evento].splice(
0 + dato.$proxy_api.eventos.para[tipo_de_evento].indexOf(evento),
1,
[nueva_accion, nueva_configuracion]
);
},
apendizar: function (tipo_de_evento, accion, nueva_accion, nueva_configuracion = {}) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
Castelog.variables.Proxificacion.comprobar_accion_o_dato_de_accion(accion);
Castelog.variables.Proxificacion.comprobar_accion(nueva_accion);
const checker = (typeof accion === "function") ? evento => evento[0] === accion : evento => evento === accion;
const evento = dato.$proxy_api.eventos.para[tipo_de_evento].filter(checker);
if (typeof evento === "undefined") {
throw new Error(`Required parameter «accion» to be known as an event function by «${tipo_de_evento}» in order to «proxificacion.$proxy_api.apendizar»`)
}
return dato.$proxy_api.eventos.para[tipo_de_evento].splice(
0 + dato.$proxy_api.eventos.para[tipo_de_evento].indexOf(evento),
0,
[nueva_accion, nueva_configuracion]
);
},
prependizar: function (tipo_de_evento, accion, nueva_accion, nueva_configuracion = {}) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
Castelog.variables.Proxificacion.comprobar_accion_o_dato_de_accion(accion);
Castelog.variables.Proxificacion.comprobar_accion(nueva_accion);
const checker = (typeof accion === "function") ? evento => evento[0] === accion : evento => evento === accion;
const evento = dato.$proxy_api.eventos.para[tipo_de_evento].filter(checker);
if (typeof evento === "undefined") {
throw new Error(`Required parameter «accion» to be known as an event function by «${tipo_de_evento}» in order to «proxificacion.$proxy_api.prependizar»`)
}
return dato.$proxy_api.eventos.para[tipo_de_evento].splice(
1 + dato.$proxy_api.eventos.para[tipo_de_evento].indexOf(evento),
0,
[nueva_accion, nueva_configuracion]
);
},
ejecutar: function (tipo_de_evento, parametros_de_proxificacion) {
Castelog.variables.Proxificacion.comprobar_tipo_de_evento(tipo_de_evento);
const [externo, clave, valor] = parametros_de_proxificacion;
if ((typeof clave === "string") && clave.startsWith("$")) {
if (tipo_de_evento === "get") {
return externo[clave];
} else if (tipo_de_evento === "set") {
return externo[clave] = valor;
} else if (tipo_de_evento === "call") {
return externo(...clave);
}
}
if(tipo_de_evento === "get") {
if((typeof clave === "string") && (clave === "toJSON")) {
return (...args) => JSON.stringify(externo, args[0] ? args[0] : null, args[1] ? args[1] : 2);
} else if ((typeof clave === "string") && (clave === "toString")) {
return () => externo;
}
}
const eventos = dato.$proxy_api.eventos.para[tipo_de_evento];
const resultado = [];
for (let index = 0; index < eventos.length; index++) {
const evento = eventos[index];
if(!Array.isArray(evento)) {
console.log(evento);
throw new Error(`Required configuration «proxificacion.$proxy_api.eventos.para.${ tipo_de_evento }» or simply «eventos» on index «${ index }» to be an array in order to «proxificacion.$proxy_api.ejecutar»`);
}
const [accion, parametros_de_accion] = evento;
Castelog.variables.Proxificacion.comprobar_accion(accion);
const salida = accion.call(externo, tipo_de_evento === "call" ? {
ambito: externo,
configuraciones: parametros_de_proxificacion,
dato: parametros_de_proxificacion[0],
clave: undefined,
valor: undefined,
parametros: parametros_de_accion,
hecho: Castelog.variables.Proxificacion.Resultado_de_proxificacion.factoria,
argumentos: parametros_de_proxificacion[1]
} : {
ambito: externo,
configuraciones: parametros_de_proxificacion,
dato: parametros_de_proxificacion[0],
clave: parametros_de_proxificacion[1],
valor: parametros_de_proxificacion[2],
parametros: parametros_de_accion,
hecho: Castelog.variables.Proxificacion.Resultado_de_proxificacion.factoria
});
if (salida instanceof Castelog.variables.Proxificacion.Resultado_de_proxificacion) {
return salida.resultado;
}
resultado.push(salida);
}
return resultado;
}
};
return dato;
}
static obtener_proxy_de_objeto(dato) {
this.extender_con_proxy_api(dato);
return new Proxy(dato, {
get: function (externo, clave) {
if (typeof externo.$proxy_api.debug === "function") {
externo.$proxy_api.debug("[DEBUG][PROXY][GETTER] Property: " + clave);
}
return dato.$proxy_api.ejecutar("get", [externo, clave]);
},
set: function (externo, clave, valor) {
if (typeof externo.$proxy_api.debug === "function") {
externo.$proxy_api.debug("[DEBUG][PROXY][SETTER] Property: " + clave);
}
return dato.$proxy_api.ejecutar("set", [externo, clave, valor]);
},
})
}
static obtener_proxy_de_funcion(dato) {
this.extender_con_proxy_api(dato);
return new Proxy(dato, {
apply: function (externo, proxificado, argumentos) {
if (typeof externo.$proxy_api.debug === "function") {
externo.$proxy_api.debug("[DEBUG][PROXY][CALLER] Arguments: " + argumentos.length + (argumentos.length ? " (" + argumentos.map(arg => typeof arg) + ")" : ""));
}
return dato.$proxy_api.ejecutar("call", [externo, argumentos]);
},
})
}
};
Castelog.variables.tipos_de_proxificacion_disponibles = [
"accede a propiedad",
"accede a cualquier propiedad",
"asigna propiedad",
"asigna cualquier propiedad",
"se llama",
];
Castelog.metodos.siempre_que_proxificacion = function(proxificacion, tipo, ...otros) {
if(!("$proxy_api" in proxificacion)) {
throw new Error("Required argument «proxificacion» to be an instance of «Castelog.variables.Proxificacion» in order to «Castelog.metodos.siempre_que_proxificacion»");
}
if(typeof tipo !== "string") {
throw new Error("Required argument «tipo» to be a string in order to «Castelog.metodos.siempre_que_proxificacion»");
}
if(Castelog.variables.tipos_de_proxificacion_disponibles.indexOf(tipo) === -1) {
throw new Error("Required argument «tipo» to be a valid string in order to «Castelog.metodos.siempre_que_proxificacion»");
}
if(otros.length === 0) {
throw new Error("Required argument «otros» to have 1 or more items in order to «Castelog.metodos.siempre_que_proxificacion»");
}
if(tipo === "accede a propiedad") {
const [ propiedad, evento ] = otros;
if(typeof propiedad !== "string") {
throw new Error("Required argument «propiedad» to be a string in order to Castelog.metodos.siempre_que_proxificacion»");
}
if (typeof evento !== "function") {
throw new Error("Required argument «evento» to be a function in order to Castelog.metodos.siempre_que_proxificacion»");
}
return proxificacion.$proxy_api.insertar("get", function(parametros) {
const { dato, clave } = parametros;
if(clave === propiedad) {
return evento(parametros);
}
}, {});
} else if (tipo === "accede a cualquier propiedad") {
const [evento] = otros;
if (typeof evento === "function") {
return proxificacion.$proxy_api.insertar("get", function (parametros) {
return evento(parametros);
}, {});
} else if(typeof evento === "object") {
if(Array.isArray(evento.deja_de) && (evento.deja_de.length > 0) && (evento.deja_de[0] === "function")) {
throw new Error("Required argument «evento.deja_de» to be a function on «accede a cualquier propiedad» in order to «Castelog.metodos.siempre_que_proxificacion»");
}
const { deja_de, en_su_lugar = null } = evento;
if(en_su_lugar === null) {
return proxificacion.$proxy_api.eliminar("get", deja_de[0]);
} else if(typeof en_su_lugar === "function") {
return proxificacion.$proxy_api.actualizar("get", deja_de[0], en_su_lugar);
} else {
throw new Error("Required argument «evento.en_su_lugar» to be a function or null on «accede a cualquier propiedad» in order to «Castelog.metodos.siempre_que_proxificacion»");
}
} else {
throw new Error("Required argument «evento» to be a function or an object on «accede a cualquier propiedad» in order to Castelog.metodos.siempre_que_proxificacion»");
}
} else if (tipo === "asigna propiedad") {
const [propiedad, evento] = otros;
if (typeof propiedad !== "string") {
throw new Error("Required argument «propiedad» to be a string in order to Castelog.metodos.siempre_que_proxificacion»");
}
if (typeof evento !== "function") {
throw new Error("Required argument «evento» to be a function in order to Castelog.metodos.siempre_que_proxificacion»");
}
return proxificacion.$proxy_api.insertar("set", function (parametros) {
const { dato, clave } = parametros;
if (clave === propiedad) {
return evento(parametros);
}
}, {});
} else if (tipo === "asigna cualquier propiedad") {
const [evento] = otros;
if (typeof evento === "function") {
return proxificacion.$proxy_api.insertar("set", function (parametros) {
return evento(parametros);
}, {});
} else if (typeof evento === "object") {
if(Array.isArray(evento.deja_de) && (evento.deja_de.length > 0) && (evento.deja_de[0] === "function")) {
throw new Error("Required argument «evento.deja_de» to be a function on «asigna cualquier propiedad» in order to «Castelog.metodos.siempre_que_proxificacion»");
}
const { deja_de, en_su_lugar = null } = evento;
if (en_su_lugar === null) {
return proxificacion.$proxy_api.eliminar("set", deja_de[0]);
} else if (typeof en_su_lugar === "function") {
return proxificacion.$proxy_api.actualizar("set", deja_de[0], en_su_lugar);
} else {
throw new Error("Required argument «evento.en_su_lugar» to be a function or null on «asigna cualquier propiedad» in order to «Castelog.metodos.siempre_que_proxificacion»");
}
} else {
throw new Error("Required argument «evento» to be a function or an object on «asigna cualquier propiedad» in order to Castelog.metodos.siempre_que_proxificacion»");
}
} else if (tipo === "se llama") {
const [evento] = otros;
if (typeof evento !== "function") {
throw new Error("Required argument «evento» to be a function in order to Castelog.metodos.siempre_que_proxificacion»");
}
return proxificacion.$proxy_api.insertar("call", function (parametros) {
return evento(parametros);
}, {});
} else {
throw new Error("Required argument «tipo» to be a valid string in order to «Castelog.metodos.siempre_que_proxificacion»")
}
};